home *** CD-ROM | disk | FTP | other *** search
/ Network PC / Network PC.iso / amiga utilities / communication / bbs / termv4.6 / extras / source / term-source.lha / Tools.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-18  |  89.9 KB  |  5,005 lines

  1. /*
  2. **    Tools.c
  3. **
  4. **    Miscellaneous support routines
  5. **
  6. **    Copyright © 1990-1996 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. */
  9.  
  10. #ifndef _GLOBAL_H
  11. #include "Global.h"
  12. #endif
  13.  
  14.     /* This variable stores the current state of the
  15.      * dialing menu items.
  16.      */
  17.  
  18. STATIC BOOLEAN DialItemsAvailable = TRUE;
  19.  
  20.     /* Current timer state. */
  21.  
  22. STATIC BOOLEAN TimerRunning;
  23.  
  24.     /* ListViewStateFill(struct LVDrawMsg *Msg):
  25.      *
  26.      *    Draw the ghosting pattern over a ghosted listview line.
  27.      */
  28.  
  29. VOID
  30. ListViewStateFill(struct LVDrawMsg *Msg)
  31. {
  32.     if(Msg->lvdm_State == LVR_SELECTEDDISABLED || Msg->lvdm_State == LVR_NORMALDISABLED)
  33.     {
  34.         ULONG         Ghosting    = 0x44441111;
  35.         struct RastPort    *RPort        = Msg->lvdm_RastPort;
  36.  
  37.         SetABPenDrMd(RPort,Msg->lvdm_DrawInfo->dri_Pens[SHADOWPEN],0,JAM1);
  38.  
  39.         SetAfPt(RPort,(UWORD *)&Ghosting,1);
  40.  
  41.         RectFill(RPort,Msg->lvdm_Bounds.MinX,Msg->lvdm_Bounds.MinY,Msg->lvdm_Bounds.MaxX,Msg->lvdm_Bounds.MaxY);
  42.  
  43.         SetAfPt(RPort,NULL,0);
  44.     }
  45. }
  46.  
  47.     /* EraseWindow(struct Window *Window):
  48.      *
  49.      *    Fills the interior of a window in the background colour.
  50.      */
  51.  
  52. VOID
  53. EraseWindow(struct Window *Window,UWORD *Pens)
  54. {
  55.     LONG Left,Top,Right,Bottom;
  56.  
  57.     Left    = Window->BorderLeft;
  58.     Top    = Window->BorderTop;
  59.     Right    = Window->Width - (Window->BorderRight + 1);
  60.     Bottom    = Window->Height - (Window->BorderBottom + 1);
  61.  
  62.     if(Pens)
  63.     {
  64.         SetPens(RPort,Pens[BACKGROUNDPEN],0,JAM1);
  65.  
  66.         RectFill(Window->RPort,Left,Top,Right,Bottom);
  67.     }
  68.     else
  69.         EraseRect(Window->RPort,Left,Top,Right,Bottom);
  70. }
  71.  
  72.     /* GetListMaxPen(UWORD *Pens):
  73.      *
  74.      *    Calculates the maximum pen number index to be
  75.      *    used for listview text rendering.
  76.      */
  77.  
  78. LONG
  79. GetListMaxPen(const UWORD *Pens)
  80. {
  81.     STATIC BYTE const PenTable[] =
  82.     {
  83.         TEXTPEN,
  84.         BACKGROUNDPEN,
  85.         FILLTEXTPEN,
  86.         FILLPEN,
  87.         SHADOWPEN,
  88.         HIGHLIGHTTEXTPEN,
  89.     };
  90.  
  91.     LONG Max,Pen,i;
  92.  
  93.     for(i = 0, Max = -1 ; i < NumElements(PenTable) ; i++)
  94.     {
  95.         Pen = Pens[PenTable[i]];
  96.  
  97.         if(Pen > Max)
  98.             Max = Pen;
  99.     }
  100.  
  101.     return(Max);
  102. }
  103.  
  104.     /* FillBox(struct RastPort *RPort,LONG Left,LONG Top,LONG Width,LONG Height):
  105.      *
  106.      *    Fill a rectangular area with the current foregroung colour.
  107.      */
  108.  
  109. VOID
  110. FillBox(struct RastPort *RPort,LONG Left,LONG Top,LONG Width,LONG Height)
  111. {
  112.     if(Width > 0 && Height > 0)
  113.         RectFill(RPort,Left,Top,Left + Width - 1,Top + Height - 1);
  114. }
  115.  
  116.     /* PlaceText(struct RastPort *RPort,LONG Left,LONG Top,STRPTR String,LONG Len):
  117.      *
  118.      *    Print some text at a specific position.
  119.      */
  120.  
  121. VOID
  122. PlaceText(struct RastPort *RPort,LONG Left,LONG Top,STRPTR String,LONG Len)
  123. {
  124.     Move(RPort,Left,Top + RPort->TxBaseline);
  125.     Text(RPort,String,Len);
  126. }
  127.  
  128.     /* SetPens(struct RastPort *RPort,ULONG APen,ULONG BPen,ULONG DrMd):
  129.      *
  130.      *    Set rendering attributes.
  131.      */
  132.  
  133. VOID
  134. SetPens(struct RastPort *RPort,ULONG APen,ULONG BPen,ULONG DrMd)
  135. {
  136.     if(Kick30)
  137.         SetABPenDrMd(RPort,APen,BPen,DrMd);
  138.     else
  139.     {
  140.         if(APen != RPort->FgPen)
  141.             SetAPen(RPort,APen);
  142.  
  143.         if(BPen != RPort->BgPen)
  144.             SetBPen(RPort,BPen);
  145.  
  146.         if(DrMd != RPort->DrawMode)
  147.             SetDrMd(RPort,DrMd);
  148.     }
  149. }
  150.  
  151.     /* VSPrintf(STRPTR Buffer,STRPTR FormatString,va_list VarArgs):
  152.      *
  153.      *    Just like vsprintf(), but using the ROM routines.
  154.      */
  155.  
  156. VOID
  157. VSPrintf(STRPTR Buffer,STRPTR FormatString,va_list VarArgs)
  158. {
  159.     RawDoFmt(FormatString,VarArgs,(VOID (*)())"\x16\xC0\x4E\x75",Buffer);
  160. }
  161.  
  162.     /* SPrintf(STRPTR Buffer,STRPTR FormatString,...):
  163.      *
  164.      *    Just like sprintf(), but using the ROM routines.
  165.      */
  166.  
  167. VOID __stdargs
  168. SPrintf(STRPTR Buffer,STRPTR FormatString,...)
  169. {
  170.     va_list VarArgs;
  171.  
  172.     va_start(VarArgs,FormatString);
  173.     VSPrintf(Buffer,FormatString,VarArgs);
  174.     va_end(VarArgs);
  175. }
  176.  
  177.     /* Atol(STRPTR Buffer):
  178.      *
  179.      *    Convert ASCII representation to long word.
  180.      */
  181.  
  182. LONG
  183. Atol(STRPTR Buffer)
  184. {
  185.     LONG Result;
  186.  
  187.     StrToLong(Buffer,&Result);
  188.  
  189.     return(Result);
  190. }
  191.  
  192.     /* StripSpaces(STRPTR String):
  193.      *
  194.      *    Strip leading and trailing spaces from a string.
  195.      */
  196.  
  197. VOID
  198. StripSpaces(STRPTR String)
  199. {
  200.     if(String)
  201.     {
  202.         STRPTR    To = String;
  203.         LONG    Len;
  204.  
  205.         while(*String == ' ')
  206.             String++;
  207.  
  208.         if(Len = strlen(String))
  209.         {
  210.             while(Len > 0 && String[Len - 1] == ' ')
  211.                 Len--;
  212.  
  213.             while(Len--)
  214.                 *To++ = *String++;
  215.         }
  216.  
  217.         *To = 0;
  218.     }
  219. }
  220.  
  221.     /* ReplaceWindowInfo(struct WindowInfo *NewInfo):
  222.      *
  223.      *    Drop the window info into the right place.
  224.      */
  225.  
  226. VOID
  227. ReplaceWindowInfo(struct WindowInfo *NewInfo)
  228. {
  229.     LONG i;
  230.  
  231.     for(i = 0 ; i < WINDOW_COUNT ; i++)
  232.     {
  233.         if(WindowInfoTable[i] . ID == NewInfo -> ID)
  234.         {
  235.             CopyMem(NewInfo,&WindowInfoTable[i],sizeof(struct WindowInfo));
  236.  
  237.             break;
  238.         }
  239.     }
  240. }
  241.  
  242.     /* PutWindowInfo():
  243.      *
  244.      *    Store window size and position relative to
  245.      *    the main window.
  246.      */
  247.  
  248. VOID
  249. PutWindowInfo(LONG ID,LONG Left,LONG Top,LONG Width,LONG Height)
  250. {
  251.     struct WindowInfo    *Info;
  252.     LONG             i;
  253.     LONG             WindowLeft,
  254.                  WindowTop,
  255.                  WindowWidth,
  256.                  WindowHeight;
  257.     ULONG             IntuiLock;
  258.  
  259.     for(i = 0 ; i < WINDOW_COUNT ; i++)
  260.     {
  261.         if(WindowInfoTable[i] . ID == ID)
  262.         {
  263.             Info = &WindowInfoTable[i];
  264.  
  265.             break;
  266.         }
  267.     }
  268.  
  269.     IntuiLock = LockIBase(NULL);
  270.  
  271.     WindowLeft    = Window -> LeftEdge;
  272.     WindowTop    = Window -> TopEdge;
  273.     WindowWidth    = Window -> Width;
  274.     WindowHeight    = Window -> Height;
  275.  
  276.     UnlockIBase(IntuiLock);
  277.  
  278.     Forbid();
  279.  
  280.     Info -> WindowFlags = NULL;
  281.  
  282.     if(WindowWidth == Width && WindowLeft == Left)
  283.         Info -> WindowFlags |= WC_EXPANDWIDTH;
  284.     else
  285.     {
  286.         if(Left == WindowLeft + WindowWidth)
  287.             Info -> WindowFlags |= WC_ALIGNSIDE;
  288.  
  289.         if(WindowLeft == Left)
  290.             Info -> WindowFlags |= WC_ALIGNLEFT;
  291.  
  292.         if(WindowLeft + WindowWidth == Left + Width)
  293.             Info -> WindowFlags |= WC_ALIGNRIGHT;
  294.     }
  295.  
  296.     if(WindowHeight == Height && WindowTop == Top)
  297.         Info -> WindowFlags |= WC_EXPANDHEIGHT;
  298.     else
  299.     {
  300.         if(Top == WindowTop + WindowHeight)
  301.             Info -> WindowFlags |= WC_ALIGNBELOW;
  302.  
  303.         if(WindowTop == Top)
  304.             Info -> WindowFlags |= WC_ALIGNTOP;
  305.  
  306.         if(WindowTop + WindowHeight == Top + Height)
  307.             Info -> WindowFlags |= WC_ALIGNBOTTOM;
  308.     }
  309.  
  310.     Info -> Left    = Left;
  311.     Info -> Top    = Top;
  312.     Info -> Width    = Width;
  313.     Info -> Height    = Height;
  314.  
  315.     Permit();
  316. }
  317.  
  318.     /* GetWindowInfo():
  319.      *
  320.      *    Set the window size and position in relation to
  321.      *    the main window.
  322.      */
  323.  
  324. VOID
  325. GetWindowInfo(LONG ID,LONG *Left,LONG *Top,LONG *Width,LONG *Height,LONG DefWidth,LONG DefHeight)
  326. {
  327.     struct WindowInfo    *Info;
  328.     LONG             i;
  329.     LONG             WindowLeft,
  330.                  WindowTop,
  331.                  WindowWidth,
  332.                  WindowHeight;
  333.     ULONG             IntuiLock;
  334.  
  335.     if(Window)
  336.     {
  337.         if(DefWidth && DefWidth < Window -> Width / 2)
  338.             DefWidth = Window -> Width / 2;
  339.  
  340.         if(DefHeight && DefHeight < Window -> Height / 2)
  341.             DefHeight = Window -> Height / 2;
  342.     }
  343.  
  344.     for(i = 0 ; i < WINDOW_COUNT ; i++)
  345.     {
  346.         if(WindowInfoTable[i] . ID == ID)
  347.         {
  348.             Info = &WindowInfoTable[i];
  349.  
  350.             break;
  351.         }
  352.     }
  353.  
  354.     if(Info && ID == WINDOW_MAIN)
  355.     {
  356.         *Left    = Info -> Left;
  357.         *Top    = Info -> Top;
  358.  
  359.         return;
  360.     }
  361.  
  362.     if(Window)
  363.     {
  364.         IntuiLock = LockIBase(NULL);
  365.  
  366.         WindowLeft    = Window -> LeftEdge;
  367.         WindowTop    = Window -> TopEdge + Window -> BorderTop;
  368.         WindowWidth    = Window -> Width;
  369.         WindowHeight    = Window -> Height - Window -> BorderTop;
  370.  
  371.         UnlockIBase(IntuiLock);
  372.     }
  373.  
  374.     Forbid();
  375.  
  376.     if(*Width)
  377.     {
  378.         if(Info -> Width)
  379.             *Left = Info -> Left;
  380.         else
  381.             *Left = WindowLeft + (WindowWidth - *Width) / 2;
  382.     }
  383.     else
  384.     {
  385.         if(DefWidth && !Info -> Width)
  386.         {
  387.             *Width    = DefWidth;
  388.             *Left    = WindowLeft + (WindowWidth - *Width) / 2;
  389.         }
  390.         else
  391.         {
  392.             if(Info -> Width)
  393.             {
  394.                 *Width    = Info -> Width;
  395.                 *Left    = Info -> Left;
  396.             }
  397.             else
  398.             {
  399.                 *Width    = WindowWidth;
  400.                 *Left    = WindowLeft;
  401.             }
  402.         }
  403.     }
  404.  
  405.     if(*Height)
  406.     {
  407.         if(Info -> Height)
  408.             *Top = Info -> Top;
  409.         else
  410.             *Top = WindowTop + (WindowHeight - *Height) / 2;
  411.     }
  412.     else
  413.     {
  414.         if(DefHeight && !Info -> Height)
  415.         {
  416.             *Height    = DefHeight;
  417.             *Top    = WindowTop + (WindowHeight - *Height) / 2;
  418.         }
  419.         else
  420.         {
  421.             if(Info -> Height)
  422.             {
  423.                 *Height    = Info -> Height;
  424.                 *Top    = Info -> Top;
  425.             }
  426.             else
  427.             {
  428.                 *Height    = WindowHeight;
  429.                 *Top    = WindowTop;
  430.             }
  431.         }
  432.     }
  433.  
  434.     if(Info -> WindowFlags & WC_ALIGNSIDE)
  435.         *Left = WindowLeft + WindowWidth;
  436.  
  437.     if(Info -> WindowFlags & WC_ALIGNBELOW)
  438.         *Top = WindowTop + WindowHeight;
  439.  
  440.     if(Info -> WindowFlags & WC_ALIGNLEFT)
  441.         *Left = WindowLeft;
  442.  
  443.     if(Info -> WindowFlags & WC_ALIGNTOP)
  444.         *Top = WindowTop;
  445.  
  446.     if(Info -> WindowFlags & WC_ALIGNRIGHT)
  447.         *Left = WindowLeft + WindowWidth - *Width;
  448.  
  449.     if(Info -> WindowFlags & WC_ALIGNBOTTOM)
  450.         *Top = WindowTop + WindowHeight - *Height;
  451.  
  452.     if(Info -> WindowFlags & WC_EXPANDWIDTH)
  453.         *Width = WindowWidth;
  454.  
  455.     if(Info -> WindowFlags & WC_EXPANDHEIGHT)
  456.         *Height = WindowHeight;
  457.  
  458.     Permit();
  459. }
  460.  
  461.     /* GetBitMapDepth(struct BitMap *BitMap):
  462.      *
  463.      *    Return the depth of a BitMap.
  464.      */
  465.  
  466. LONG
  467. GetBitMapDepth(struct BitMap *BitMap)
  468. {
  469.     LONG Depth;
  470.  
  471.     if(Kick30)
  472.         Depth = (LONG)GetBitMapAttr(BitMap,BMA_DEPTH);
  473.     else
  474.         Depth = BitMap -> Depth;
  475.  
  476.     if(Depth > 8)
  477.         Depth = 8;
  478.  
  479.     return(Depth);
  480. }
  481.  
  482.     /* GetDPI(ULONG Mode,ULONG *X_DPI,ULONG *Y_DPI):
  483.      *
  484.      *    Get screen DPI resolution values.
  485.      */
  486.  
  487. VOID
  488. GetDPI(ULONG Mode,ULONG *X_DPI,ULONG *Y_DPI)
  489. {
  490.     struct DisplayInfo DisplayInfo;
  491.  
  492.     *X_DPI = *Y_DPI = 72;
  493.  
  494.     if(GetDisplayInfoData(NULL,(APTR)&DisplayInfo,sizeof(struct DisplayInfo),DTAG_DISP,Mode))
  495.     {
  496.         if(DisplayInfo . PixelSpeed && DisplayInfo . Resolution . x && DisplayInfo . Resolution . y)
  497.         {
  498.             *X_DPI = (35 * 140) / DisplayInfo . PixelSpeed;
  499.             *Y_DPI = (*X_DPI * DisplayInfo . Resolution . x) / DisplayInfo . Resolution . y;
  500.         }
  501.     }
  502. }
  503.  
  504.     /* AddProtection(STRPTR FileName,ULONG Mask):
  505.      *
  506.      *    Set bits in the protection mask of a file.
  507.      */
  508.  
  509. VOID
  510. AddProtection(STRPTR Name,ULONG Mask)
  511. {
  512.     struct FileInfoBlock *FileInfo;
  513.  
  514.     if(FileInfo = (struct FileInfoBlock *)AllocDosObject(DOS_FIB,TAG_DONE))
  515.     {
  516.         BPTR FileLock;
  517.  
  518.         if(FileLock = Lock(Name,ACCESS_READ))
  519.         {
  520.             if(Examine(FileLock,FileInfo))
  521.             {
  522.                 UnLock(FileLock);
  523.  
  524.                 SetProtection(Name,FileInfo -> fib_Protection | Mask);
  525.             }
  526.             else
  527.                 UnLock(FileLock);
  528.         }
  529.  
  530.         FreeDosObject(DOS_FIB,FileInfo);
  531.     }
  532. }
  533.  
  534.     /* GetPubScreenName(struct Screen *Screen,STRPTR Name):
  535.      *
  536.      *    Get the name of a public screen.
  537.      */
  538.  
  539. BOOL
  540. GetPubScreenName(struct Screen *Screen,STRPTR Name)
  541. {
  542.     struct List        *PubScreenList;
  543.     struct PubScreenNode    *ScreenNode;
  544.  
  545.     PubScreenList = LockPubScreenList();
  546.  
  547.     for(ScreenNode = (struct PubScreenNode *)PubScreenList -> lh_Head ; ScreenNode -> psn_Node . ln_Succ ; ScreenNode = (struct PubScreenNode *)ScreenNode -> psn_Node . ln_Succ)
  548.     {
  549.         if(ScreenNode -> psn_Screen == Screen)
  550.         {
  551.             strcpy(Name,ScreenNode -> psn_Node . ln_Name);
  552.  
  553.             UnlockPubScreenList();
  554.  
  555.             return(TRUE);
  556.         }
  557.     }
  558.  
  559.     UnlockPubScreenList();
  560.  
  561.     return(FALSE);
  562. }
  563.  
  564.     /* InitSinglePort(struct MsgPort *Port):
  565.      *
  566.      *    Initialize a plain MsgPort (as created on the stack) for
  567.      *    usage. Don't try this at home, kids!
  568.      */
  569.  
  570. VOID
  571. InitSinglePort(struct MsgPort *Port)
  572. {
  573.     memset(Port,0,sizeof(struct MsgPort));
  574.  
  575.     Port -> mp_Flags    = PA_SIGNAL;
  576.     Port -> mp_SigBit    = SIGB_SINGLE;
  577.     Port -> mp_SigTask    = FindTask(NULL);
  578.  
  579.     NewList(&Port -> mp_MsgList);
  580. }
  581.  
  582.     /* GoodStream(BPTR Stream):
  583.      *
  584.      *    Check to see whether the current input file
  585.      *    is an interactive stream.
  586.      */
  587.  
  588. BOOL
  589. GoodStream(BPTR Stream)
  590. {
  591.     if(!Stream)
  592.         Stream = Input();
  593.  
  594.     if(Stream)
  595.     {
  596.         struct FileHandle *Handle = (struct FileHandle *)BADDR(Stream);
  597.  
  598.         if(Handle -> fh_Type)
  599.         {
  600.             if(IsInteractive(Stream))
  601.                 return(TRUE);
  602.         }
  603.     }
  604.  
  605.     return(FALSE);
  606. }
  607.  
  608.     /* GetProgramIcon():
  609.      *
  610.      *    Try to find the icon of the program.
  611.      */
  612.  
  613. struct DiskObject *
  614. GetProgramIcon()
  615. {
  616.     struct DiskObject *Icon = NULL;
  617.  
  618.         /* Run from Workbench? */
  619.  
  620.     if(WBenchMsg)
  621.     {
  622.             /* Sanity check. */
  623.  
  624.         if(WBenchMsg -> sm_ArgList)
  625.         {
  626.                 /* Yet another sanity check. */
  627.  
  628.             if(WBenchMsg -> sm_ArgList -> wa_Name)
  629.             {
  630.                     /* Try to find the icon in the current directory. */
  631.  
  632.                 if(Icon = GetDiskObjectNew(WBenchMsg -> sm_ArgList -> wa_Name))
  633.                 {
  634.                     if(Icon -> do_Type != WBTOOL)
  635.                     {
  636.                         FreeDiskObject(Icon);
  637.  
  638.                         Icon = NULL;
  639.                     }
  640.                 }
  641.  
  642.                 if(!Icon)
  643.                 {
  644.                     BPTR NewLock;
  645.  
  646.                         /* Move to the directory the
  647.                          * program was run from.
  648.                          */
  649.  
  650.                     if(NewLock = Lock("PROGDIR:",ACCESS_READ))
  651.                     {
  652.                         BPTR OldLock;
  653.  
  654.                         OldLock = CurrentDir(NewLock);
  655.  
  656.                             /* Try to fetch the icon, use the
  657.                              * default name if necessary.
  658.                              */
  659.  
  660.                         if(Icon = GetDiskObjectNew(WBenchMsg -> sm_ArgList -> wa_Name))
  661.                         {
  662.                             if(Icon -> do_Type != WBTOOL)
  663.                             {
  664.                                 FreeDiskObject(Icon);
  665.  
  666.                                 Icon = NULL;
  667.                             }
  668.                         }
  669.  
  670.                         if(!Icon)
  671.                         {
  672.                             if(Icon = GetDiskObjectNew("term"))
  673.                             {
  674.                                 if(Icon -> do_Type != WBTOOL)
  675.                                 {
  676.                                     FreeDiskObject(Icon);
  677.  
  678.                                     Icon = NULL;
  679.                                 }
  680.                             }
  681.                         }
  682.  
  683.                         CurrentDir(OldLock);
  684.  
  685.                         UnLock(NewLock);
  686.                     }
  687.                 }
  688.             }
  689.         }
  690.     }
  691.  
  692.         /* Still no success. */
  693.  
  694.     if(!Icon)
  695.     {
  696.             /* Use the default names. */
  697.  
  698.         if(Icon = GetDiskObjectNew("term"))
  699.         {
  700.             if(Icon -> do_Type != WBTOOL)
  701.             {
  702.                 FreeDiskObject(Icon);
  703.  
  704.                 Icon = NULL;
  705.             }
  706.         }
  707.  
  708.         if(!Icon)
  709.         {
  710.             if(Icon = GetDiskObjectNew("PROGDIR:term"))
  711.             {
  712.                 if(Icon -> do_Type != WBTOOL)
  713.                 {
  714.                     FreeDiskObject(Icon);
  715.  
  716.                     Icon = NULL;
  717.                 }
  718.             }
  719.         }
  720.     }
  721.  
  722.     return(Icon);
  723. }
  724.  
  725.     /* GetPenIndex(LONG Pen):
  726.      *
  727.      *    Get the table index corresponding to an on-screen
  728.      *    text rendering pen.
  729.      */
  730.  
  731. LONG
  732. GetPenIndex(LONG Pen)
  733. {
  734.     LONG i;
  735.  
  736.     for(i = 0 ; i < 16 ; i++)
  737.     {
  738.         if(MappedPens[0][i] == Pen)
  739.             return(i);
  740.     }
  741. }
  742.  
  743.     /* GetScreenWidth(struct Window *Window):
  744.      *
  745.      *    Query the current screen width.
  746.      */
  747.  
  748. LONG
  749. GetScreenWidth(struct Window *Window)
  750. {
  751.     if(Window)
  752.     {
  753.         if(Window -> Width > ScreenWidth || Window -> LeftEdge < -Window -> WScreen -> LeftEdge || Window -> LeftEdge + Window -> WScreen -> LeftEdge + Window -> Width > ScreenWidth)
  754.             return(ScreenWidth);
  755.         else
  756.             return(Window -> Width - (Window -> BorderLeft + Window -> BorderRight));
  757.     }
  758.     else
  759.         return(ScreenWidth);
  760. }
  761.  
  762.     /* GetScreenHeight(struct Window *Window):
  763.      *
  764.      *    Query the current screen height.
  765.      */
  766.  
  767. LONG
  768. GetScreenHeight(struct Window *Window)
  769. {
  770.     if(Window)
  771.     {
  772.         if(Window -> Height > ScreenHeight || Window -> TopEdge < -Window -> WScreen -> TopEdge || Window -> TopEdge + Window -> WScreen -> TopEdge + Window -> Height > ScreenHeight)
  773.             return(ScreenHeight);
  774.         else
  775.             return(Window -> Height - (Window -> BorderTop + Window -> BorderBottom));
  776.     }
  777.     else
  778.         return(ScreenHeight);
  779. }
  780.  
  781.     /* GetLeft(struct Screen *Screen):
  782.      *
  783.      *    Get the screen left edge.
  784.      */
  785.  
  786. STATIC LONG
  787. GetLeft(struct Screen *Screen)
  788. {
  789.     if(Screen -> LeftEdge >= 0)
  790.         return(0);
  791.     else
  792.         return(-Screen -> LeftEdge);
  793. }
  794.  
  795.     /* GetScreenLeft(struct Window *Window):
  796.      *
  797.      *    Query the current screen left edge.
  798.      */
  799.  
  800. LONG
  801. GetScreenLeft(struct Window *Window)
  802. {
  803.     if(Window)
  804.     {
  805.         if(Window -> Width > ScreenWidth || Window -> LeftEdge < -Window -> WScreen -> LeftEdge || Window -> LeftEdge + Window -> WScreen -> LeftEdge + Window -> Width > ScreenWidth)
  806.             return(GetLeft(Window -> WScreen));
  807.         else
  808.             return(Window -> LeftEdge + Window -> BorderLeft);
  809.     }
  810.     else
  811.     {
  812.         struct Screen *PubScreen = LockPubScreen(NULL);
  813.         LONG Result;
  814.  
  815.         Result = GetLeft(PubScreen ? PubScreen : SharedScreen);
  816.  
  817.         UnlockPubScreen(NULL,PubScreen);
  818.  
  819.         return(Result);
  820.     }
  821. }
  822.  
  823.     /* GetTop(struct Screen *Screen):
  824.      *
  825.      *    Get the screen top edge.
  826.      */
  827.  
  828. STATIC LONG
  829. GetTop(struct Screen *Screen)
  830. {
  831.     if(Screen -> TopEdge >= 0)
  832.         return(0);
  833.     else
  834.         return(-Screen -> TopEdge);
  835. }
  836.  
  837.     /* GetScreenTop(struct Window *Window):
  838.      *
  839.      *    Query the current screen top edge.
  840.      */
  841.  
  842. LONG
  843. GetScreenTop(struct Window *Window)
  844. {
  845.     if(Window)
  846.     {
  847.         if(Window -> Height > ScreenHeight || Window -> TopEdge < -Window -> WScreen -> TopEdge || Window -> TopEdge + Window -> WScreen -> TopEdge + Window -> Height > ScreenHeight)
  848.             return(GetTop(Window -> WScreen));
  849.         else
  850.             return(Window -> TopEdge + Window -> BorderTop);
  851.     }
  852.     else
  853.     {
  854.         struct Screen *PubScreen = LockPubScreen(NULL);
  855.         LONG Result;
  856.  
  857.         Result = GetTop(PubScreen ? PubScreen : SharedScreen);
  858.  
  859.         UnlockPubScreen(NULL,PubScreen);
  860.  
  861.         return(Result);
  862.     }
  863. }
  864.  
  865.     /* OldGetAPen(struct RastPort *RPort):
  866.      *
  867.      *    Query the current primary rendering colour (old style).
  868.      */
  869.  
  870. ULONG
  871. OldGetAPen(struct RastPort *RPort)
  872. {
  873.     return((ULONG)RPort -> FgPen);
  874. }
  875.  
  876.     /* OldGetBPen(struct RastPort *RPort):
  877.      *
  878.      *    Query the current seconary rendering colour (old style).
  879.      */
  880.  
  881. ULONG
  882. OldGetBPen(struct RastPort *RPort)
  883. {
  884.     return((ULONG)RPort -> BgPen);
  885. }
  886.  
  887.     /* OldGetDrMd(struct RastPort *RPort):
  888.      *
  889.      *    Query the current drawing mode (old style).
  890.      */
  891.  
  892. ULONG
  893. OldGetDrMd(struct RastPort *RPort)
  894. {
  895.     return((ULONG)RPort -> DrawMode);
  896. }
  897.  
  898.     /* OldSetWrMsk(struct RastPort *RPort,ULONG Mask):
  899.      *
  900.      *    Set the rendering plane mask (old style).
  901.      */
  902.  
  903. ULONG
  904. OldSetWrMsk(struct RastPort *RPort,ULONG Mask)
  905. {
  906.     if(UseMasking)
  907.         RPort -> Mask = Mask;
  908.  
  909.     return((ULONG)1);
  910. }
  911.  
  912.     /* NewGetAPen(struct RastPort *RPort):
  913.      *
  914.      *    Query the current primary rendering colour (new style).
  915.      */
  916.  
  917. ULONG
  918. NewGetAPen(struct RastPort *RPort)
  919. {
  920.     return(GetAPen(RPort));
  921. }
  922.  
  923.     /* NewGetBPen(struct RastPort *RPort):
  924.      *
  925.      *    Query the current seconary rendering colour (new style).
  926.      */
  927.  
  928. ULONG
  929. NewGetBPen(struct RastPort *RPort)
  930. {
  931.     return(GetBPen(RPort));
  932. }
  933.  
  934.     /* NewGetDrMd(struct RastPort *RPort):
  935.      *
  936.      *    Query the current drawing mode (new style).
  937.      */
  938.  
  939. ULONG
  940. NewGetDrMd(struct RastPort *RPort)
  941. {
  942.     return(GetDrMd(RPort));
  943. }
  944.  
  945.     /* NewSetWrMsk(struct RastPort *RPort,ULONG Mask):
  946.      *
  947.      *    Set the rendering plane mask (new style).
  948.      */
  949.  
  950. ULONG
  951. NewSetWrMsk(struct RastPort *RPort,ULONG Mask)
  952. {
  953.     if(UseMasking)
  954.         return(SetWriteMask(RPort,Mask));
  955.     else
  956.         return((ULONG)1);
  957. }
  958.  
  959.     /* SetWait(struct Window *Window):
  960.      *
  961.      *    Set the busy wait mouse pointer.
  962.      */
  963.  
  964. VOID
  965. SetWait(struct Window *Window)
  966. {
  967.         // Note: now requires gtlayout.library to do all the hard work
  968.  
  969.     if(GTLayoutBase)
  970.         LT_LockWindow(Window);
  971. }
  972.  
  973.     /* ClrWait(struct Window *Window):
  974.      *
  975.      *    Remove the busy wait mouse pointer.
  976.      */
  977.  
  978. VOID
  979. ClrWait(struct Window *Window)
  980. {
  981.     if(GTLayoutBase)
  982.         LT_UnlockWindow(Window);
  983. }
  984.  
  985.     /* GetModeName(ULONG Mode):
  986.      *
  987.      *    Get the name of a display mode.
  988.      */
  989.  
  990. STRPTR
  991. GetModeName(ULONG Mode)
  992. {
  993.     STATIC UBYTE    Buffer[DISPLAYNAMELEN + 1];
  994.     struct NameInfo    NameInfo;
  995.  
  996.     if(GetDisplayInfoData(NULL,(APTR)&NameInfo,sizeof(struct NameInfo),DTAG_NAME,Mode))
  997.         strcpy(Buffer,NameInfo . Name);
  998.     else
  999.     {
  1000.         struct DimensionInfo DimensionInfo;
  1001.  
  1002.         if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,Mode))
  1003.         {
  1004.             STRPTR MonitorName;
  1005.  
  1006.             switch(Mode & MONITOR_ID_MASK)
  1007.             {
  1008.                 case NTSC_MONITOR_ID:
  1009.  
  1010.                     MonitorName = "NTSC:";
  1011.                     break;
  1012.  
  1013.                 case PAL_MONITOR_ID:
  1014.  
  1015.                     MonitorName = "PAL:";
  1016.                     break;
  1017.  
  1018.                 case VGA_MONITOR_ID:
  1019.  
  1020.                     MonitorName = "VGA:";
  1021.                     break;
  1022.  
  1023.                 case A2024_MONITOR_ID:
  1024.  
  1025.                     MonitorName = "A2024:";
  1026.                     break;
  1027.  
  1028.                 default:
  1029.  
  1030.                     MonitorName = "";
  1031.                     break;
  1032.             }
  1033.  
  1034.             SPrintf(Buffer,"%s%ldx%ld",MonitorName,DimensionInfo . TxtOScan . MaxX - DimensionInfo . TxtOScan . MinX + 1,DimensionInfo . TxtOScan . MaxY - DimensionInfo . TxtOScan . MinY + 1);
  1035.         }
  1036.         else
  1037.             strcpy(Buffer,LocaleString(MSG_SCREENPANEL_UNKNOWN_TXT));
  1038.     }
  1039.  
  1040.     return(Buffer);
  1041. }
  1042.  
  1043.     /* ModeOkay(ULONG ID):
  1044.      *
  1045.      *    Checks whether a display mode ID will do for deep
  1046.      *    screen bitmaps.
  1047.      */
  1048.  
  1049. BOOL
  1050. ModeOkay(ULONG ID)
  1051. {
  1052.     struct DimensionInfo DimensionInfo;
  1053.  
  1054.     if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,ID))
  1055.     {
  1056.         if(DimensionInfo . MaxDepth >= 4)
  1057.             return(TRUE);
  1058.     }
  1059.  
  1060.     return(FALSE);
  1061. }
  1062.  
  1063.     /* SetClipMenu(BYTE Mode):
  1064.      *
  1065.      *    Enable/disable the copy/clear selection menu items.
  1066.      */
  1067.  
  1068. VOID
  1069. SetClipMenu(BOOL Mode)
  1070. {
  1071.     if(Mode && RasterEnabled)
  1072.     {
  1073.         OnItem(MEN_COPY);
  1074.         OnItem(MEN_CLEAR);
  1075.     }
  1076.     else
  1077.     {
  1078.         OffItem(MEN_COPY);
  1079.         OffItem(MEN_CLEAR);
  1080.     }
  1081. }
  1082.  
  1083.     /* SetRedialMenu():
  1084.      *
  1085.      *    Make the `redial' menu item available or make it
  1086.      *    unavailable.
  1087.      */
  1088.  
  1089. VOID
  1090. SetRedialMenu()
  1091. {
  1092.     BOOL Mode;
  1093.  
  1094.     if(DialList)
  1095.     {
  1096.         if(DialList -> lh_Head -> ln_Succ)
  1097.             Mode = TRUE;
  1098.         else
  1099.             Mode = FALSE;
  1100.     }
  1101.     else
  1102.         Mode = FALSE;
  1103.  
  1104.     if(Mode && (DialItemsAvailable || Config -> MiscConfig -> ProtectiveMode))
  1105.         OnItem(MEN_REDIAL);
  1106.     else
  1107.         OffItem(MEN_REDIAL);
  1108. }
  1109.  
  1110.     /* SetDialMenu(BOOL Mode):
  1111.      *
  1112.      *    Block or enable the dialing menu.
  1113.      */
  1114.  
  1115. VOID
  1116. SetDialMenu(BOOL Mode)
  1117. {
  1118.     if(Window && Menu)
  1119.     {
  1120.         if(Mode || Config -> MiscConfig -> ProtectiveMode)
  1121.         {
  1122.             if(DialList)
  1123.             {
  1124.                 if(DialList -> lh_Head -> ln_Succ)
  1125.                     OnItem(MEN_REDIAL);
  1126.                 else
  1127.                     OffItem(MEN_REDIAL);
  1128.             }
  1129.             else
  1130.                 OffItem(MEN_REDIAL);
  1131.  
  1132.             OnItem(MEN_DIAL_NUMBER);
  1133.  
  1134.             if(FirstDialMenu != -1)
  1135.                 OnItem(MEN_EXTRA_DIAL);
  1136.         }
  1137.         else
  1138.         {
  1139.             OffItem(MEN_REDIAL);
  1140.             OffItem(MEN_DIAL_NUMBER);
  1141.  
  1142.             if(FirstDialMenu != -1)
  1143.                 OffItem(MEN_EXTRA_DIAL);
  1144.         }
  1145.  
  1146.         DialItemsAvailable = Mode;
  1147.     }
  1148. }
  1149.  
  1150.     /* SetTransferMenu(BOOL Mode):
  1151.      *
  1152.      *    Block or enable the transfer menu.
  1153.      */
  1154.  
  1155. VOID
  1156. SetTransferMenu(BOOL Mode)
  1157. {
  1158.     if(Window && Menu)
  1159.     {
  1160.         BOOL    ValidDefault,
  1161.             ValidASCIIDownload,
  1162.             ValidASCIIUpload,
  1163.             ValidTextDownload,
  1164.             ValidTextUpload,
  1165.             ValidBinaryDownload,
  1166.             ValidBinaryUpload;
  1167.  
  1168.         if(!Config -> TransferConfig -> DefaultLibrary[0] || !Mode || (!XProtocolBase && Config -> TransferConfig -> DefaultType == XFER_XPR))
  1169.             ValidDefault = FALSE;
  1170.         else
  1171.             ValidDefault = TRUE;
  1172.  
  1173.         switch(Config -> TransferConfig -> ASCIIUploadType)
  1174.         {
  1175.             case XFER_INTERNAL:
  1176.  
  1177.                 ValidASCIIUpload = TRUE;
  1178.                 break;
  1179.  
  1180.             case XFER_DEFAULT:
  1181.  
  1182.                 ValidASCIIUpload = ValidDefault;
  1183.                 break;
  1184.  
  1185.             case XFER_XPR:
  1186.             case XFER_EXTERNALPROGRAM:
  1187.  
  1188.                 ValidASCIIUpload = Config -> TransferConfig -> ASCIIUploadLibrary[0];
  1189.                 break;
  1190.         }
  1191.  
  1192.         switch(Config -> TransferConfig -> ASCIIDownloadType)
  1193.         {
  1194.             case XFER_INTERNAL:
  1195.  
  1196.                 ValidASCIIDownload = TRUE;
  1197.                 break;
  1198.  
  1199.             case XFER_DEFAULT:
  1200.  
  1201.                 ValidASCIIDownload = ValidDefault;
  1202.                 break;
  1203.  
  1204.             case XFER_XPR:
  1205.             case XFER_EXTERNALPROGRAM:
  1206.  
  1207.                 ValidASCIIDownload = Config -> TransferConfig -> ASCIIDownloadLibrary[0];
  1208.                 break;
  1209.         }
  1210.  
  1211.  
  1212.         switch(Config -> TransferConfig -> TextUploadType)
  1213.         {
  1214.             case XFER_DEFAULT:
  1215.  
  1216.                 ValidTextUpload = ValidDefault;
  1217.                 break;
  1218.  
  1219.             case XFER_XPR:
  1220.             case XFER_EXTERNALPROGRAM:
  1221.  
  1222.                 ValidTextUpload = Config -> TransferConfig -> TextUploadLibrary[0];
  1223.                 break;
  1224.         }
  1225.  
  1226.         switch(Config -> TransferConfig -> TextDownloadType)
  1227.         {
  1228.             case XFER_DEFAULT:
  1229.  
  1230.                 ValidTextDownload = ValidDefault;
  1231.                 break;
  1232.  
  1233.             case XFER_XPR:
  1234.             case XFER_EXTERNALPROGRAM:
  1235.  
  1236.                 ValidTextDownload = Config -> TransferConfig -> TextDownloadLibrary[0];
  1237.                 break;
  1238.         }
  1239.  
  1240.         switch(Config -> TransferConfig -> BinaryUploadType)
  1241.         {
  1242.             case XFER_DEFAULT:
  1243.  
  1244.                 ValidBinaryUpload = ValidDefault;
  1245.                 break;
  1246.  
  1247.             case XFER_XPR:
  1248.             case XFER_EXTERNALPROGRAM:
  1249.  
  1250.                 ValidBinaryUpload = Config -> TransferConfig -> BinaryUploadLibrary[0];
  1251.                 break;
  1252.         }
  1253.  
  1254.         switch(Config -> TransferConfig -> BinaryDownloadType)
  1255.         {
  1256.             case XFER_DEFAULT:
  1257.  
  1258.                 ValidBinaryDownload = ValidDefault;
  1259.                 break;
  1260.  
  1261.             case XFER_XPR:
  1262.             case XFER_EXTERNALPROGRAM:
  1263.  
  1264.                 ValidBinaryDownload = Config -> TransferConfig -> BinaryDownloadLibrary[0];
  1265.                 break;
  1266.         }
  1267.  
  1268.         if(ValidASCIIUpload)
  1269.             OnItem(MEN_UPLOAD_ASCII);
  1270.         else
  1271.             OffItem(MEN_UPLOAD_ASCII);
  1272.  
  1273.         if(ValidASCIIDownload)
  1274.             OnItem(MEN_DOWNLOAD_ASCII);
  1275.         else
  1276.             OffItem(MEN_DOWNLOAD_ASCII);
  1277.  
  1278.         if(ValidTextUpload)
  1279.         {
  1280.             OnItem(MEN_UPLOAD_TEXT);
  1281.             OnItem(MEN_EDIT_AND_UPLOAD_TEXT);
  1282.         }
  1283.         else
  1284.         {
  1285.             OffItem(MEN_UPLOAD_TEXT);
  1286.             OffItem(MEN_EDIT_AND_UPLOAD_TEXT);
  1287.         }
  1288.  
  1289.         if(ValidTextDownload)
  1290.             OnItem(MEN_DOWNLOAD_TEXT);
  1291.         else
  1292.             OffItem(MEN_DOWNLOAD_TEXT);
  1293.  
  1294.         if(ValidBinaryUpload)
  1295.             OnItem(MEN_UPLOAD_BINARY);
  1296.         else
  1297.             OffItem(MEN_UPLOAD_BINARY);
  1298.  
  1299.         if(ValidBinaryDownload)
  1300.             OnItem(MEN_DOWNLOAD_BINARY);
  1301.         else
  1302.             OffItem(MEN_DOWNLOAD_BINARY);
  1303.  
  1304.         if(ValidDefault)
  1305.             OnItem(MEN_TRANSFER);
  1306.         else
  1307.             OffItem(MEN_TRANSFER);
  1308.     }
  1309. }
  1310.  
  1311.     /* SetRasterMenu(BOOL Mode):
  1312.      *
  1313.      *    Block or enable the menu entries associated with
  1314.      *    functions to access the screen raster.
  1315.      */
  1316.  
  1317. VOID
  1318. SetRasterMenu(BOOL Mode)
  1319. {
  1320.     if(Window && Menu)
  1321.     {
  1322.         if(Mode)
  1323.         {
  1324.             OnItem(MEN_SAVE_AS_TEXT);
  1325.             OnItem(MEN_PRINT_SCREEN);
  1326.         }
  1327.         else
  1328.         {
  1329.             OffItem(MEN_SAVE_AS_TEXT);
  1330.             OffItem(MEN_PRINT_SCREEN);
  1331.         }
  1332.     }
  1333. }
  1334.  
  1335.     /* PickFont(struct Window *Window,STRPTR Name,WORD *Points,BOOL MonoSpaced):
  1336.      *
  1337.      *    Pick a font using asl.library
  1338.      */
  1339.  
  1340. BOOL
  1341. PickFont(struct Window *Window,STRPTR Name,WORD *Points,BOOL MonoSpaced)
  1342. {
  1343.     struct TagItem             DimensionTags[5];
  1344.     struct FontRequester        *Requester;
  1345.     BOOL                 Result = FALSE;
  1346.  
  1347.     if(Requester = (struct FontRequester *)AllocAslRequestTags(ASL_FontRequest,
  1348.         ASLFO_Window,        Window,
  1349.         ASLFO_InitialName,    Name,
  1350.         ASLFO_InitialSize,    *Points,
  1351.         ASLFO_InitialFrontPen,    Pens[TEXTPEN],
  1352.         ASLFO_InitialBackPen,    Pens[BACKGROUNDPEN],
  1353.         ASLFO_PrivateIDCMP,    TRUE,
  1354.         ASLFO_MaxHeight,    255,        // Excessive!
  1355.  
  1356.         ASL_FuncFlags,        MonoSpaced ? (FONF_NEWIDCMP|FONF_FIXEDWIDTH) : FONF_NEWIDCMP,
  1357.     TAG_MORE,GetDimensionTags(NULL,DimensionTags)))
  1358.     {
  1359.         LT_LockWindow(Window);
  1360.  
  1361.         if(AslRequest(Requester,NULL))
  1362.         {
  1363.             PutDimensionTags(NULL,Requester -> fo_LeftEdge,Requester -> fo_TopEdge,Requester -> fo_Width,Requester -> fo_Height);
  1364.  
  1365.             strcpy(Name,Requester -> fo_Attr . ta_Name);
  1366.  
  1367.             *Points = Requester -> fo_Attr . ta_YSize;
  1368.  
  1369.             Result = TRUE;
  1370.         }
  1371.  
  1372.         LT_UnlockWindow(Window);
  1373.  
  1374.         FreeAslRequest(Requester);
  1375.     }
  1376.  
  1377.     return(Result);
  1378. }
  1379.  
  1380.     /* ExtractString():
  1381.      *
  1382.      *    Extracts a string from a list separated by `|' characters.
  1383.      */
  1384.  
  1385. STRPTR
  1386. ExtractString(STRPTR String,STRPTR Destination,BOOL ReturnEnd)
  1387. {
  1388.     STRPTR OldString;
  1389.  
  1390.     if(ReturnEnd)
  1391.         OldString = NULL;
  1392.     else
  1393.         OldString = String;
  1394.  
  1395.     while(*String)
  1396.     {
  1397.         if(*String == '|')
  1398.         {
  1399.             *Destination = 0;
  1400.  
  1401.             String++;
  1402.  
  1403.             if(*String)
  1404.                 return(String);
  1405.             else
  1406.                 return(OldString);
  1407.         }
  1408.         else
  1409.             *Destination++ = *String++;
  1410.     }
  1411.  
  1412.     *Destination = 0;
  1413.  
  1414.     return(OldString);
  1415. }
  1416.  
  1417.     /* GetListSize(struct List *List):
  1418.      *
  1419.      *    Determine the number of entries in a list.
  1420.      */
  1421.  
  1422. LONG
  1423. GetListSize(struct List *List)
  1424. {
  1425.     struct Node    *Node    = List -> lh_Head;
  1426.     LONG         i    = 0;
  1427.  
  1428.     while(Node -> ln_Succ)
  1429.     {
  1430.         i++;
  1431.  
  1432.         Node = Node -> ln_Succ;
  1433.     }
  1434.  
  1435.     return(i);
  1436. }
  1437.  
  1438.     /* GetListNode(LONG Offset,struct List *List):
  1439.      *
  1440.      *    Return the n-th Node entry in a standard exec list.
  1441.      */
  1442.  
  1443. struct Node *
  1444. GetListNode(LONG Offset,struct List *List)
  1445. {
  1446.     if(Offset < 0)
  1447.         return(NULL);
  1448.     else
  1449.     {
  1450.         struct Node    *Node;
  1451.         LONG         i;
  1452.  
  1453.         Node = List -> lh_Head;
  1454.  
  1455.         for(i = 0 ; i < Offset ; i++)
  1456.         {
  1457.             if(!Node -> ln_Succ -> ln_Succ)
  1458.                 return(NULL);
  1459.  
  1460.             Node = Node -> ln_Succ;
  1461.         }
  1462.  
  1463.         return(Node);
  1464.     }
  1465. }
  1466.  
  1467.     /* CreateNode(STRPTR Name):
  1468.      *
  1469.      *    Put a name string into a list node.
  1470.      */
  1471.  
  1472. struct Node *
  1473. CreateNode(STRPTR Name)
  1474. {
  1475.     struct Node *Node;
  1476.  
  1477.     if(Node = (struct Node *)AllocVecPooled(sizeof(struct Node) + strlen(Name) + 1,MEMF_ANY | MEMF_PUBLIC))
  1478.     {
  1479.         Node -> ln_Name = (STRPTR)(Node + 1);
  1480.  
  1481.         strcpy(Node -> ln_Name,Name);
  1482.     }
  1483.  
  1484.     return(Node);
  1485. }
  1486.  
  1487.     /* FreeNode(struct Node *Node):
  1488.      *
  1489.      *    Remove and deallocate a node.
  1490.      */
  1491.  
  1492. VOID
  1493. FreeNode(struct Node *Node)
  1494. {
  1495.     Remove(Node);
  1496.  
  1497.     FreeVecPooled(Node);
  1498. }
  1499.  
  1500.     /* FreeList(struct List *List):
  1501.      *
  1502.      *    Remove all nodes from the list
  1503.      *    and free them on the way.
  1504.      */
  1505.  
  1506. VOID
  1507. FreeList(struct List *List)
  1508. {
  1509.     struct Node *Node;
  1510.  
  1511.     while(Node = RemHead(List))
  1512.         FreeVecPooled(Node);
  1513. }
  1514.  
  1515.     /* GetNodeOffset(struct Node *Node,struct List *List):
  1516.      *
  1517.      *    Scan a list for a certain node and return
  1518.      *    its position.
  1519.      */
  1520.  
  1521. LONG
  1522. GetNodeOffset(struct Node *Node,struct List *List)
  1523. {
  1524.     struct Node    *ListNode;
  1525.     LONG         Offset = 0;
  1526.  
  1527.     ListNode = List -> lh_Head;
  1528.  
  1529.     while(ListNode -> ln_Succ)
  1530.     {
  1531.         if(Node == ListNode)
  1532.             return(Offset);
  1533.         else
  1534.         {
  1535.             Offset++;
  1536.  
  1537.             ListNode = ListNode -> ln_Succ;
  1538.         }
  1539.     }
  1540.  
  1541.     return(~0);
  1542. }
  1543.  
  1544.     /* MoveList(struct List *From,struct List *To):
  1545.      *
  1546.      *    Move the contents of a list to a different list.
  1547.      */
  1548.  
  1549. VOID
  1550. MoveList(struct List *From,struct List *To)
  1551. {
  1552.     struct Node *Node;
  1553.  
  1554.     while(Node = RemHead(From))
  1555.         AddTail(To,Node);
  1556. }
  1557.  
  1558.     /* LogAction(STRPTR String,...):
  1559.      *
  1560.      *    Write an action to the default log file.
  1561.      */
  1562.  
  1563. VOID __stdargs
  1564. LogAction(STRPTR String,...)
  1565. {
  1566.     if(Config -> CaptureConfig -> LogActions && Config -> CaptureConfig -> LogFileName[0])
  1567.     {
  1568.         UBYTE    DummyBuffer[512];
  1569.         BPTR    File;
  1570.  
  1571.         va_list    VarArgs;
  1572.  
  1573.             /* Build a valid string. */
  1574.  
  1575.         va_start(VarArgs,String);
  1576.         VSPrintf(DummyBuffer,String,VarArgs);
  1577.         va_end(VarArgs);
  1578.  
  1579.             /* Does the log file already exist? */
  1580.  
  1581.         if(GetFileSize(Config -> CaptureConfig -> LogFileName))
  1582.         {
  1583.                 /* It does, let's append the data. */
  1584.  
  1585.             if(File = Open(Config -> CaptureConfig -> LogFileName,MODE_READWRITE))
  1586.             {
  1587.                 if(Seek(File,0,OFFSET_END) == -1)
  1588.                 {
  1589.                     Close(File);
  1590.  
  1591.                     File = NULL;
  1592.                 }
  1593.             }
  1594.         }
  1595.         else
  1596.         {
  1597.                 /* Create a new file. */
  1598.  
  1599.             if(File = Open(Config -> CaptureConfig -> LogFileName,MODE_NEWFILE))
  1600.                 FPrintf(File,LocaleString(MSG_TERMAUX_DATE_TIME_ACTION_TXT));
  1601.         }
  1602.  
  1603.             /* The file is open, build the date/time string and
  1604.              * write the log action.
  1605.              */
  1606.  
  1607.         if(File)
  1608.         {
  1609.             UBYTE        DateBuffer[40],
  1610.                     TimeBuffer[40];
  1611.             struct DateTime    DateTime;
  1612.  
  1613.             DateStamp(&DateTime . dat_Stamp);
  1614.  
  1615.             DateTime . dat_Format    = FORMAT_DOS;
  1616.             DateTime . dat_Flags    = NULL;
  1617.             DateTime . dat_StrDay    = NULL;
  1618.             DateTime . dat_StrDate    = DateBuffer;
  1619.             DateTime . dat_StrTime    = TimeBuffer;
  1620.  
  1621.             if(DateToStr(&DateTime))
  1622.             {
  1623.                 StripSpaces(TimeBuffer);
  1624.  
  1625.                 FPrintf(File,"%-9s %8s %s\n",DateBuffer,TimeBuffer,DummyBuffer);
  1626.             }
  1627.  
  1628.                 /* Done! */
  1629.  
  1630.             Close(File);
  1631.         }
  1632.     }
  1633. }
  1634.  
  1635.     /* FlushMsg(struct Window *Window):
  1636.      *
  1637.      *    Cancel all pending messages of a window.
  1638.      */
  1639.  
  1640. VOID
  1641. FlushMsg(struct Window *Window)
  1642. {
  1643.     struct IntuiMessage *Massage;
  1644.  
  1645.     while(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
  1646.         ReplyMsg(&Massage -> ExecMessage);
  1647. }
  1648.  
  1649.     /* GetString(STRPTR Prompt,STRPTR Buffer):
  1650.      *
  1651.      *    Get a string from the user, very much the same as xpr_gets,
  1652.      *    but also including the `Load File' gadget.
  1653.      */
  1654.  
  1655. BOOL
  1656. GetString(BOOL LoadGadget,BOOL Password,LONG MaxChars,STRPTR Prompt,STRPTR Buffer)
  1657. {
  1658.     enum    {    GAD_OK=1,GAD_CANCEL,GAD_STRING };
  1659.  
  1660.     struct LayoutHandle    *Handle;
  1661.     BOOL             Success = FALSE;
  1662.     UBYTE             LocalBuffer[256];
  1663.  
  1664.     if(!MaxChars)
  1665.         MaxChars = 255;
  1666.  
  1667.     if(MaxChars > 255)
  1668.     {
  1669.         CopyMem(Buffer,LocalBuffer,255);
  1670.  
  1671.         LocalBuffer[255] = 0;
  1672.  
  1673.         MaxChars = 255;
  1674.     }
  1675.     else
  1676.         strcpy(LocalBuffer,Buffer);
  1677.  
  1678.     if(!Prompt)
  1679.         Prompt = LocaleString(MSG_TERMXPR_INPUT_REQUIRED_TXT);
  1680.  
  1681.     if(Handle = LT_CreateHandleTags(Window -> WScreen,
  1682.         LH_LocaleHook,    &LocaleHook,
  1683.     TAG_DONE))
  1684.     {
  1685.         struct Window *PanelWindow;
  1686.  
  1687.         LT_New(Handle,
  1688.             LA_Type,    VERTICAL_KIND,
  1689.         TAG_DONE);
  1690.         {
  1691.             LT_New(Handle,
  1692.                 LA_Type,    VERTICAL_KIND,
  1693.                 LA_LabelText,    Prompt,
  1694.             TAG_DONE);
  1695.             {
  1696.                 if(Password)
  1697.                 {
  1698.                     LT_New(Handle,
  1699.                         LA_Type,    PASSWORD_KIND,
  1700.                         LA_STRPTR,    LocalBuffer,
  1701.                         LA_ID,        GAD_STRING,
  1702.                         LA_Chars,    40,
  1703.                         GTST_MaxChars,    MaxChars,
  1704.                     TAG_DONE);
  1705.                 }
  1706.                 else
  1707.                 {
  1708.                     LT_New(Handle,
  1709.                         LA_Type,    STRING_KIND,
  1710.                         LA_STRPTR,    LocalBuffer,
  1711.                         LA_ID,        GAD_STRING,
  1712.                         LA_Chars,    60,
  1713.                         LAST_Picker,    LoadGadget,
  1714.                     TAG_DONE);
  1715.                 }
  1716.  
  1717.                 LT_EndGroup(Handle);
  1718.             }
  1719.  
  1720.             LT_New(Handle,
  1721.                 LA_Type,VERTICAL_KIND,
  1722.             TAG_DONE);
  1723.             {
  1724.                 LT_New(Handle,
  1725.                     LA_Type,    XBAR_KIND,
  1726.                     LAXB_FullSize,    TRUE,
  1727.                 TAG_DONE);
  1728.  
  1729.                 LT_EndGroup(Handle);
  1730.             }
  1731.  
  1732.             LT_New(Handle,LA_Type,HORIZONTAL_KIND,
  1733.                 LAGR_SameSize,    TRUE,
  1734.                 LAGR_Spread,    TRUE,
  1735.             TAG_DONE);
  1736.             {
  1737.                 LT_New(Handle,
  1738.                     LA_Type,    BUTTON_KIND,
  1739.                     LA_LabelID,    MSG_TERMXPR_OKAY_GAD,
  1740.                     LA_ID,        GAD_OK,
  1741.                     LABT_ReturnKey,    TRUE,
  1742.                     LABT_ExtraFat,    TRUE,
  1743.                 TAG_DONE);
  1744.  
  1745.                 LT_New(Handle,
  1746.                     LA_Type,    BUTTON_KIND,
  1747.                     LA_LabelID,    MSG_GLOBAL_CANCEL_GAD,
  1748.                     LA_ID,        GAD_CANCEL,
  1749.                     LABT_EscKey,    TRUE,
  1750.                     LABT_ExtraFat,    TRUE,
  1751.                 TAG_DONE);
  1752.  
  1753.                 LT_EndGroup(Handle);
  1754.             }
  1755.         }
  1756.  
  1757.         if(PanelWindow = LT_Build(Handle,
  1758.             LAWN_TitleID,        MSG_GLOBAL_ENTER_TEXT_TXT,
  1759.             LAWN_IDCMP,        IDCMP_CLOSEWINDOW,
  1760.             LAWN_HelpHook,        &GuideHook,
  1761.             LAWN_Parent,        Window,
  1762.             WA_DepthGadget,        TRUE,
  1763.             WA_CloseGadget,        TRUE,
  1764.             WA_DragBar,        TRUE,
  1765.             WA_RMBTrap,        TRUE,
  1766.             WA_Activate,        TRUE,
  1767.             WA_SimpleRefresh,    TRUE,
  1768.         TAG_DONE))
  1769.         {
  1770.             struct IntuiMessage    *Message;
  1771.             BOOL             Done = FALSE;
  1772.             ULONG             MsgClass;
  1773.             UWORD             MsgCode;
  1774.             struct Gadget        *MsgGadget;
  1775.  
  1776.             LT_Activate(Handle,GAD_STRING);
  1777.  
  1778.             PushWindow(PanelWindow);
  1779.  
  1780.             LT_ShowWindow(Handle,TRUE);
  1781.  
  1782.             do
  1783.             {
  1784.                 if(Wait(PORTMASK(PanelWindow -> UserPort) | SIG_BREAK) & SIG_BREAK)
  1785.                     break;
  1786.  
  1787.                 while(Message = (struct IntuiMessage *)LT_GetIMsg(Handle))
  1788.                 {
  1789.                     MsgClass    = Message -> Class;
  1790.                     MsgCode        = Message -> Code;
  1791.                     MsgGadget    = (struct Gadget *)Message -> IAddress;
  1792.  
  1793.                     LT_ReplyIMsg(Message);
  1794.  
  1795.                     if(MsgClass == IDCMP_CLOSEWINDOW)
  1796.                         Done = TRUE;
  1797.  
  1798.                     if(MsgClass == IDCMP_GADGETUP)
  1799.                     {
  1800.                         switch(MsgGadget -> GadgetID)
  1801.                         {
  1802.                             case GAD_STRING:
  1803.  
  1804.                                 if(MsgCode == '\r')
  1805.                                 {
  1806.                                     LT_UpdateStrings(Handle);
  1807.  
  1808.                                     strcpy(Buffer,LocalBuffer);
  1809.  
  1810.                                     Success = Done = TRUE;
  1811.  
  1812.                                     LT_PressButton(Handle,GAD_OK);
  1813.                                 }
  1814.  
  1815.                                 break;
  1816.  
  1817.                             case GAD_OK:
  1818.  
  1819.                                 LT_UpdateStrings(Handle);
  1820.  
  1821.                                 strcpy(Buffer,LocalBuffer);
  1822.  
  1823.                                 Success = Done = TRUE;
  1824.                                 break;
  1825.  
  1826.                             case GAD_CANCEL:
  1827.  
  1828.                                 Done = TRUE;
  1829.                                 break;
  1830.                         }
  1831.                     }
  1832.  
  1833.                     if(MsgClass == IDCMP_IDCMPUPDATE && MsgGadget -> GadgetID == GAD_STRING)
  1834.                     {
  1835.                         UBYTE             DummyBuffer[MAX_FILENAME_LENGTH],
  1836.                                     *DummyChar;
  1837.                         struct FileRequester    *FileRequest;
  1838.  
  1839.                         SplitFileName(LocalBuffer,&DummyChar,DummyBuffer);
  1840.  
  1841.                         if(FileRequest = GetFile(PanelWindow,LocaleString(MSG_TERMAUX_LOAD_FILE_TXT),DummyBuffer,DummyChar,DummyBuffer,NULL,FALSE,FALSE,FALSE,LocaleString(MSG_GLOBAL_SELECT_TXT),TRUE))
  1842.                         {
  1843.                             LT_SetAttributes(Handle,GAD_STRING,GTST_String,DummyBuffer,TAG_DONE);
  1844.  
  1845.                             FreeAslRequest(FileRequest);
  1846.                         }
  1847.                     }
  1848.                 }
  1849.             }
  1850.             while(!Done);
  1851.  
  1852.             PopWindow();
  1853.         }
  1854.  
  1855.         LT_DeleteHandle(Handle);
  1856.     }
  1857.  
  1858.     return(Success);
  1859. }
  1860.  
  1861.     /* WakeUp(struct Window *Window,LONG Sound):
  1862.      *
  1863.      *    Pop a window to the front and alert the user.
  1864.      */
  1865.  
  1866. VOID
  1867. WakeUp(struct Window *Window,LONG Sound)
  1868. {
  1869.     if(Window)
  1870.     {
  1871.         if(Config -> MiscConfig -> AlertMode == ALERT_SCREEN || Config -> MiscConfig -> AlertMode == ALERT_BEEP_SCREEN)
  1872.         {
  1873.             if(Window -> WScreen -> LeftEdge > 0)
  1874.             {
  1875.                 if(Window -> WScreen -> TopEdge > 0)
  1876.                     MoveScreen(Window -> WScreen,-Window -> WScreen -> LeftEdge,-Window -> WScreen -> TopEdge);
  1877.                 else
  1878.                     MoveScreen(Window -> WScreen,-Window -> WScreen -> LeftEdge,0);
  1879.             }
  1880.             else
  1881.             {
  1882.                 if(Window -> WScreen -> TopEdge > 0)
  1883.                     MoveScreen(Window -> WScreen,0,-Window -> WScreen -> TopEdge);
  1884.             }
  1885.  
  1886.             WindowToFront(Window);
  1887.  
  1888.             ScreenToFront(Window -> WScreen);
  1889.         }
  1890.     }
  1891.  
  1892.     if(Sound != SOUND_BELL || Config -> MiscConfig -> AlertMode == ALERT_BEEP || Config -> MiscConfig -> AlertMode == ALERT_BEEP_SCREEN)
  1893.         SoundPlay(Sound);
  1894. }
  1895.  
  1896.     /* TaskDestructor(struct DataMsg *Item):
  1897.      *
  1898.      *    Msg destructor for the routines below.
  1899.      */
  1900.  
  1901. STATIC VOID __stdargs
  1902. TaskDestructor(struct DataMsg *Item)
  1903. {
  1904.     Signal((struct Process *)Item -> Data,SIGBREAKF_CTRL_F);
  1905. }
  1906.  
  1907.     /* AmigaDOSBackgroundServer(VOID):
  1908.      *
  1909.      *    Background process to handle tool execution.
  1910.      */
  1911.  
  1912. STATIC VOID __saveds
  1913. AmigaDOSBackgroundServer(VOID)
  1914. {
  1915.     STATIC ULONG DefaultTags[] =
  1916.     {
  1917.         SYS_UserShell,TRUE,
  1918.         TAG_DONE
  1919.     };
  1920.  
  1921.     BPTR         NewCOS = NULL;
  1922.     struct DataMsg     Msg;
  1923.     STRPTR         Command;
  1924.     struct Process    *Me;
  1925.  
  1926.         /* Look who we are. */
  1927.  
  1928.     Me = (struct Process *)FindTask(NULL);
  1929.  
  1930.     Command = Me -> pr_Task . tc_UserData;
  1931.  
  1932.         /* Create console output stream, will be closed automagically on exit. */
  1933.  
  1934.     if(!Output() && GetConsoleTask())
  1935.     {
  1936.         if(NewCOS = Open("CONSOLE:",MODE_NEWFILE))
  1937.             SelectOutput(NewCOS);
  1938.     }
  1939.  
  1940.     SystemTagList(Command,(struct TagItem *)DefaultTags);
  1941.  
  1942.     FreeVecPooled(Command);
  1943.  
  1944.     Forbid();
  1945.  
  1946.     InitMsgItem(&Msg,TaskDestructor);
  1947.  
  1948.     Msg . Type = DATAMSGTYPE_COMMANDDONE;
  1949.     Msg . Data = (UBYTE *)Me;
  1950.  
  1951.     ClrSignal(SIGBREAKF_CTRL_F);
  1952.  
  1953.     PutMsgItem(SpecialQueue,(struct MsgItem *)&Msg);
  1954.  
  1955.     Wait(SIGBREAKF_CTRL_F);
  1956.  
  1957.     if(NewCOS)
  1958.     {
  1959.         SelectOutput(NULL);
  1960.         Close(NewCOS);
  1961.     }
  1962. }
  1963.  
  1964.     /* SendAmigaDOSCommand(STRPTR Name):
  1965.      *
  1966.      *    Let the current default Shell execute an AmigaDOS
  1967.      *    command. Block until the command has returned.
  1968.      */
  1969.  
  1970. VOID
  1971. SendAmigaDOSCommand(STRPTR Name)
  1972. {
  1973.     STRPTR NewName;
  1974.  
  1975.     if(NewName = (STRPTR)AllocVecPooled(strlen(Name) + 1 + 256,MEMF_ANY))
  1976.     {
  1977.         struct Process    *NewProcess;
  1978.         BPTR         Stream;
  1979.         STRPTR         NewWindowName;
  1980.  
  1981.         strcpy(NewName,Name);
  1982.  
  1983.         NewWindowName = NewName + strlen(NewName) + 1;
  1984.  
  1985.         BlockWindows();
  1986.  
  1987.         SetQueueDiscard(SpecialQueue,FALSE);
  1988.  
  1989.             /* Open the output file. */
  1990.  
  1991.         if(WindowName[0])
  1992.         {
  1993.             UBYTE LocalName[MAXPUBSCREENNAME + 1];
  1994.  
  1995.             if(Window)
  1996.             {
  1997.                 if(!GetPubScreenName(Window -> WScreen,LocalName))
  1998.                     LocalName[0] = 0;
  1999.             }
  2000.  
  2001.             if(LocalName[0])
  2002.             {
  2003.                 SPrintf(NewWindowName,WindowName,LocalName);
  2004.  
  2005.                 Stream = Open(NewWindowName,MODE_NEWFILE);
  2006.             }
  2007.             else
  2008.                 Stream = Open(WindowName,MODE_NEWFILE);
  2009.         }
  2010.         else
  2011.             Stream = NULL;
  2012.  
  2013.         Forbid();
  2014.  
  2015.         if(NewProcess = LaunchProcess("term AmigaDOS Background Process",AmigaDOSBackgroundServer,Stream))
  2016.         {
  2017.             CantQuit++;
  2018.  
  2019.             NewProcess -> pr_Task . tc_UserData = NewName;
  2020.  
  2021.             Permit();
  2022.         }
  2023.         else
  2024.         {
  2025.             Permit();
  2026.  
  2027.             if(Stream)
  2028.                 Close(Stream);
  2029.  
  2030.             FreeVecPooled(NewName);
  2031.  
  2032.             BumpWindow(Window);
  2033.  
  2034.             ReleaseWindows();
  2035.         }
  2036.     }
  2037. }
  2038.  
  2039.     /* RexxBackgroundServer():
  2040.      *
  2041.      *    The background process to handle the rexx
  2042.      *    massaging.
  2043.      */
  2044.  
  2045. STATIC VOID __saveds
  2046. RexxBackgroundServer(VOID)
  2047. {
  2048.     struct MsgPort     *RexxPort;
  2049.     BPTR         NewCOS = NULL;
  2050.     struct DataMsg     Msg;
  2051.     STRPTR         Command;
  2052.     struct Process    *Me;
  2053.  
  2054.         /* Look who we are. */
  2055.  
  2056.     Me = (struct Process *)FindTask(NULL);
  2057.  
  2058.     Command = Me -> pr_Task . tc_UserData;
  2059.  
  2060.         /* Create console output stream, will be closed automagically on exit. */
  2061.  
  2062.     if(!Output() && GetConsoleTask())
  2063.     {
  2064.         if(NewCOS = Open("CONSOLE:",MODE_NEWFILE))
  2065.             SelectOutput(NewCOS);
  2066.     }
  2067.  
  2068.     if(RexxPort = FindPort(RXSDIR))
  2069.     {
  2070.         struct MsgPort __aligned     ReplyPort;
  2071.         struct RexxMsg            *RexxMsg;
  2072.  
  2073.         InitSinglePort(&ReplyPort);
  2074.  
  2075.         if(RexxMsg = CreateRexxMsg(&ReplyPort,"term",RexxPortName))
  2076.         {
  2077.             if(RexxMsg -> rm_Args[0] = CreateArgstring(Command,strlen(Command)))
  2078.             {
  2079.                 RexxMsg -> rm_Action = RXCOMM;
  2080.  
  2081.                 Forbid();
  2082.  
  2083.                 ClrSignal(SIGF_SINGLE);
  2084.  
  2085.                 PutMsg(RexxPort,(struct Message *)RexxMsg);
  2086.  
  2087.                 WaitPort(&ReplyPort);
  2088.  
  2089.                 GetMsg(&ReplyPort);
  2090.  
  2091.                 Permit();
  2092.  
  2093.                     /* This doesn't look too
  2094.                      * good, does it?
  2095.                      */
  2096.  
  2097.                 if(RexxMsg -> rm_Result1 && Output())
  2098.                     Printf(LocaleString(MSG_TERMAUX_COMMAND_HAS_TERMINATED_TXT),Command,RexxMsg -> rm_Result1,RexxMsg -> rm_Result2);
  2099.  
  2100.                 DeleteArgstring(RexxMsg -> rm_Args[0]);
  2101.             }
  2102.  
  2103.             DeleteRexxMsg(RexxMsg);
  2104.         }
  2105.     }
  2106.  
  2107.     FreeVecPooled(Command);
  2108.  
  2109.     Forbid();
  2110.  
  2111.     InitMsgItem(&Msg,TaskDestructor);
  2112.  
  2113.     Msg . Type = DATAMSGTYPE_COMMANDDONE;
  2114.     Msg . Data = (UBYTE *)Me;
  2115.  
  2116.     ClrSignal(SIGBREAKF_CTRL_F);
  2117.  
  2118.     PutMsgItem(SpecialQueue,(struct MsgItem *)&Msg);
  2119.  
  2120.     Wait(SIGBREAKF_CTRL_F);
  2121.  
  2122.     if(NewCOS)
  2123.     {
  2124.         SelectOutput(NULL);
  2125.  
  2126.         Close(NewCOS);
  2127.     }
  2128. }
  2129.  
  2130.     /* SendARexxCommand(STRPTR Name,BOOL QueueIt):
  2131.      *
  2132.      *    Let the ARexx server execute a command (or a script
  2133.      *    file if necessary) and block until the command
  2134.      *    has returned.
  2135.      */
  2136.  
  2137. VOID
  2138. SendARexxCommand(STRPTR Name,BOOL QueueIt)
  2139. {
  2140.     STRPTR NewName;
  2141.  
  2142.     if(QueueIt)
  2143.     {
  2144.         ObtainSemaphore(&ARexxQueueSemaphore);
  2145.  
  2146.         if(ARexxRunning)
  2147.         {
  2148.             struct Node *Node;
  2149.  
  2150.             if(Node = CreateNode(Name))
  2151.                 AddTail(&ARexxQueue,Node);
  2152.  
  2153.             ReleaseSemaphore(&ARexxQueueSemaphore);
  2154.  
  2155.             return;
  2156.         }
  2157.     }
  2158.  
  2159.     if(NewName = (STRPTR)AllocVecPooled(strlen(Name) + 1 + 256,MEMF_ANY))
  2160.     {
  2161.         struct Process    *NewProcess;
  2162.         BPTR         Stream;
  2163.         STRPTR         NewWindowName;
  2164.  
  2165.         strcpy(NewName,Name);
  2166.  
  2167.         NewWindowName = NewName + strlen(NewName) + 1;
  2168.  
  2169.         BlockWindows();
  2170.  
  2171.         SetQueueDiscard(SpecialQueue,FALSE);
  2172.  
  2173.             /* Open the output file. */
  2174.  
  2175.         if(WindowName[0])
  2176.         {
  2177.             UBYTE LocalName[MAXPUBSCREENNAME + 1];
  2178.  
  2179.             if(Window)
  2180.             {
  2181.                 if(!GetPubScreenName(Window -> WScreen,LocalName))
  2182.                     LocalName[0] = 0;
  2183.             }
  2184.  
  2185.             if(LocalName[0])
  2186.             {
  2187.                 SPrintf(NewWindowName,WindowName,LocalName);
  2188.  
  2189.                 Stream = Open(NewWindowName,MODE_NEWFILE);
  2190.             }
  2191.             else
  2192.                 Stream = Open(WindowName,MODE_NEWFILE);
  2193.         }
  2194.         else
  2195.             Stream = NULL;
  2196.  
  2197.         Forbid();
  2198.  
  2199.             /* Create the background process which will
  2200.              * handle all the messy rexx message sending
  2201.              * for us.
  2202.              */
  2203.  
  2204.         if(NewProcess = LaunchProcess("term ARexx Background Process",RexxBackgroundServer,Stream))
  2205.         {
  2206.             CantQuit++;
  2207.  
  2208.             NewProcess -> pr_Task . tc_UserData = NewName;
  2209.  
  2210.             Permit();
  2211.  
  2212.             if(QueueIt)
  2213.                 ARexxRunning = TRUE;
  2214.         }
  2215.         else
  2216.         {
  2217.             Permit();
  2218.  
  2219.             if(Stream)
  2220.                 Close(Stream);
  2221.  
  2222.             FreeVecPooled(NewName);
  2223.  
  2224.             BumpWindow(Window);
  2225.  
  2226.             ReleaseWindows();
  2227.         }
  2228.     }
  2229.  
  2230.     if(QueueIt)
  2231.         ReleaseSemaphore(&ARexxQueueSemaphore);
  2232. }
  2233.  
  2234.     /* BlockWindows():
  2235.      *
  2236.      *    Block the main window and the status window (i.e. disable
  2237.      *    the menu and attach a wait pointer).
  2238.      */
  2239.  
  2240. VOID
  2241. BlockWindows()
  2242. {
  2243.     if(!(BlockNestCount++))
  2244.     {
  2245.         LT_LockWindow(Window);
  2246.         LT_LockWindow(StatusWindow);
  2247.         LT_LockWindow(FastWindow);
  2248.         LT_LockWindow(MatrixWindow);
  2249.  
  2250.         WeAreBlocking = TRUE;
  2251.  
  2252.         SetQueueDiscard(SpecialQueue,TRUE);
  2253.  
  2254.         GhostCursor();
  2255.     }
  2256. }
  2257.  
  2258.     /* ReleaseWindows():
  2259.      *
  2260.      *    Reenable the menus and clear the wait pointer.
  2261.      */
  2262.  
  2263. VOID
  2264. ReleaseWindows()
  2265. {
  2266.     if(BlockNestCount == 1)
  2267.     {
  2268.         LT_UnlockWindow(Window);
  2269.         LT_UnlockWindow(StatusWindow);
  2270.         LT_UnlockWindow(FastWindow);
  2271.         LT_UnlockWindow(MatrixWindow);
  2272.  
  2273.         WeAreBlocking = FALSE;
  2274.  
  2275.         SetQueueDiscard(SpecialQueue,FALSE);
  2276.  
  2277.         if(Window)
  2278.         {
  2279.             Forbid();
  2280.  
  2281.             if(Window -> Flags & WFLG_WINDOWACTIVE)
  2282.                 NormalCursor();
  2283.  
  2284.             Permit();
  2285.         }
  2286.     }
  2287.  
  2288.     if(BlockNestCount)
  2289.         BlockNestCount--;
  2290. }
  2291.  
  2292.     /* LineRead(BPTR File,STRPTR Buffer,LONG MaxChars):
  2293.      *
  2294.      *    Read a few bytes from a file (à la gets).
  2295.      */
  2296.  
  2297. LONG
  2298. LineRead(BPTR File,STRPTR Buffer,LONG MaxChars)
  2299. {
  2300.     STATIC UBYTE    Data[1024];
  2301.     STATIC LONG    ReadIndex,ReadLen;
  2302.  
  2303.     if(File)
  2304.     {
  2305.         LONG BytesRead = 0,i;
  2306.  
  2307.         for(i = 0 ; i < MaxChars ; i++)
  2308.         {
  2309.             if(ReadIndex >= ReadLen)
  2310.             {
  2311.                 ReadLen = Read(File,Data,1024);
  2312.  
  2313.                 ReadIndex = 0;
  2314.  
  2315.                 if(ReadLen <= 0)
  2316.                 {
  2317.                     Buffer[i] = 0;
  2318.  
  2319.                     return(BytesRead);
  2320.                 }
  2321.             }
  2322.  
  2323.             BytesRead++;
  2324.  
  2325.             if((Buffer[i] = Data[ReadIndex++]) == '\n')
  2326.             {
  2327.                 Buffer[i + 1] = 0;
  2328.  
  2329.                 return(BytesRead);
  2330.             }
  2331.         }
  2332.  
  2333.         return(BytesRead);
  2334.     }
  2335.     else
  2336.         ReadIndex = ReadLen = 0;
  2337. }
  2338.  
  2339.     /* GetBaudRate(STRPTR Buffer):
  2340.      *
  2341.      *    Calculate the baud rate contained in a connect string.
  2342.      */
  2343.  
  2344. LONG
  2345. GetBaudRate(STRPTR Buffer)
  2346. {
  2347.     LONG Rate,i,j;
  2348.  
  2349.     for(i = j = 0 ; i < strlen(Buffer) ; i++)
  2350.     {
  2351.         if(Buffer[i] == ' ')
  2352.             continue;
  2353.         else
  2354.         {
  2355.             if(Buffer[i] >= '0' && Buffer[i] <= '9')
  2356.                 SharedBuffer[j++] = Buffer[i];
  2357.             else
  2358.                 break;
  2359.         }
  2360.     }
  2361.  
  2362.     SharedBuffer[j] = 0;
  2363.  
  2364.     if(StrToLong(SharedBuffer,&Rate) > 0)
  2365.     {
  2366.         if(Rate > 0)
  2367.             return(Rate);
  2368.     }
  2369.  
  2370.     return(0);
  2371. }
  2372.  
  2373.     /* LookForIt(struct MenuItem *Item,ULONG ID):
  2374.      *
  2375.      *    Auxilary routine for FindThisItem(), scans
  2376.      *    menu item and sub item lists.
  2377.      */
  2378.  
  2379. STATIC struct MenuItem *
  2380. LookForIt(struct MenuItem *Item,ULONG ID)
  2381. {
  2382.     while(Item)
  2383.     {
  2384.         if((ULONG)GTMENUITEM_USERDATA(Item) == ID)
  2385.             return(Item);
  2386.         else
  2387.         {
  2388.             if(Item -> SubItem)
  2389.             {
  2390.                 register struct MenuItem *TheItem;
  2391.  
  2392.                 if(TheItem = LookForIt(Item -> SubItem,ID))
  2393.                     return(TheItem);
  2394.             }
  2395.  
  2396.             Item = Item -> NextItem;
  2397.         }
  2398.     }
  2399.  
  2400.     return(NULL);
  2401. }
  2402.  
  2403.     /* FindThisItem(struct Menu *FirstMenu,ULONG MenuID):
  2404.      *
  2405.      *    Scan a menu for a menuitem associated with a
  2406.      *    menu ID.
  2407.      */
  2408.  
  2409. struct MenuItem *
  2410. FindThisItem(struct Menu *FirstMenu,ULONG MenuID)
  2411. {
  2412.     if(TypeOfMem(FirstMenu))
  2413.     {
  2414.         struct MenuItem *Item;
  2415.  
  2416.         while(FirstMenu)
  2417.         {
  2418.             if(Item = LookForIt(FirstMenu -> FirstItem,MenuID))
  2419.                 return(Item);
  2420.             else
  2421.                 FirstMenu = FirstMenu -> NextMenu;
  2422.         }
  2423.     }
  2424.  
  2425.     return(NULL);
  2426. }
  2427.  
  2428. struct Menu *
  2429. FindThisMenu(struct Menu *FirstMenu,ULONG MenuID)
  2430. {
  2431.     if(TypeOfMem(FirstMenu))
  2432.     {
  2433.         while(FirstMenu)
  2434.         {
  2435.             if(GTMENU_USERDATA(FirstMenu) == (APTR)MenuID)
  2436.                 return(FirstMenu);
  2437.             else
  2438.                 FirstMenu = FirstMenu -> NextMenu;
  2439.         }
  2440.     }
  2441.  
  2442.     return(NULL);
  2443. }
  2444.  
  2445.     /* GetItem(ULONG MenuID):
  2446.      *
  2447.      *    Get the checkmark state of a menu item.
  2448.      */
  2449.  
  2450. BOOL
  2451. GetItem(ULONG MenuID)
  2452. {
  2453.     if(Menu)
  2454.     {
  2455.         struct MenuItem *Item;
  2456.  
  2457.         if(Item = FindThisItem(Menu,MenuID))
  2458.         {
  2459.             if(Item -> Flags & CHECKED)
  2460.                 return(TRUE);
  2461.         }
  2462.     }
  2463.  
  2464.     return(FALSE);
  2465. }
  2466.  
  2467.     /* SetItem(ULONG MenuID,BOOL Mode):
  2468.      *
  2469.      *    Clear or set the checkmark or state of a menu item.
  2470.      */
  2471.  
  2472. VOID
  2473. SetItem(ULONG MenuID,BOOL Mode)
  2474. {
  2475.         /* Is the global pull-down menu available? */
  2476.  
  2477.     if(Menu)
  2478.     {
  2479.         struct MenuItem    *Item;
  2480.         struct Menu    *ThisMenu;
  2481.  
  2482.         if(ThisMenu = FindThisMenu(Menu,MenuID))
  2483.         {
  2484.                 /* Remove the menu from the windows. */
  2485.  
  2486.             if(Window)
  2487.                 ClearMenuStrip(Window);
  2488.  
  2489.             if(StatusWindow)
  2490.                 ClearMenuStrip(StatusWindow);
  2491.  
  2492.             if(FastWindow)
  2493.                 ClearMenuStrip(FastWindow);
  2494.  
  2495.             switch(Mode)
  2496.             {
  2497.                 case SETITEM_ON:
  2498.  
  2499.                     ThisMenu -> Flags |= MENUENABLED;
  2500.                     break;
  2501.  
  2502.                 case SETITEM_OFF:
  2503.  
  2504.                     ThisMenu -> Flags &= ~MENUENABLED;
  2505.                     break;
  2506.             }
  2507.  
  2508.                 /* Reattach the menu to the windows. */
  2509.  
  2510.             if(Window)
  2511.                 ResetMenuStrip(Window,Menu);
  2512.  
  2513.             if(StatusWindow)
  2514.                 ResetMenuStrip(StatusWindow,Menu);
  2515.  
  2516.             if(FastWindow)
  2517.                 ResetMenuStrip(FastWindow,Menu);
  2518.  
  2519.             return;
  2520.         }
  2521.  
  2522.             /* Try to find the menu item and change
  2523.              * the state of the checkmark.
  2524.              */
  2525.  
  2526.         if(Item = FindThisItem(Menu,MenuID))
  2527.         {
  2528.                 /* Remove the menu from the windows. */
  2529.  
  2530.             if(Window)
  2531.                 ClearMenuStrip(Window);
  2532.  
  2533.             if(StatusWindow)
  2534.                 ClearMenuStrip(StatusWindow);
  2535.  
  2536.             if(FastWindow)
  2537.                 ClearMenuStrip(FastWindow);
  2538.  
  2539.             switch(Mode)
  2540.             {
  2541.                 case SETITEM_SETCHECK:
  2542.  
  2543.                     Item -> Flags |= CHECKED;
  2544.                     break;
  2545.  
  2546.                 case SETITEM_CLRCHECK:
  2547.  
  2548.                     Item -> Flags &= ~CHECKED;
  2549.                     break;
  2550.  
  2551.                 case SETITEM_ON:
  2552.  
  2553.                     Item -> Flags |= ITEMENABLED;
  2554.                     break;
  2555.  
  2556.                 case SETITEM_OFF:
  2557.  
  2558.                     Item -> Flags &= ~ITEMENABLED;
  2559.                     break;
  2560.             }
  2561.  
  2562.                 /* Reattach the menu to the windows. */
  2563.  
  2564.             if(Window)
  2565.                 ResetMenuStrip(Window,Menu);
  2566.  
  2567.             if(StatusWindow)
  2568.                 ResetMenuStrip(StatusWindow,Menu);
  2569.  
  2570.             if(FastWindow)
  2571.                 ResetMenuStrip(FastWindow,Menu);
  2572.         }
  2573.     }
  2574. }
  2575.  
  2576.     /* GetFileSize(STRPTR Name):
  2577.      *
  2578.      *    Simple routine to return the size of a file in
  2579.      *    bytes.
  2580.      */
  2581.  
  2582. LONG
  2583. GetFileSize(STRPTR Name)
  2584. {
  2585.     struct FileInfoBlock    *FileInfo;
  2586.     LONG             FileSize = 0;
  2587.  
  2588.     if(FileInfo = (struct FileInfoBlock *)AllocDosObject(DOS_FIB,TAG_DONE))
  2589.     {
  2590.         BPTR FileLock;
  2591.  
  2592.         if(FileLock = Lock(Name,ACCESS_READ))
  2593.         {
  2594.             if(Examine(FileLock,FileInfo))
  2595.             {
  2596.                 if(FileInfo -> fib_DirEntryType < 0)
  2597.                     FileSize = FileInfo -> fib_Size;
  2598.             }
  2599.  
  2600.             UnLock(FileLock);
  2601.         }
  2602.  
  2603.         FreeDosObject(DOS_FIB,FileInfo);
  2604.     }
  2605.  
  2606.     return(FileSize);
  2607. }
  2608.  
  2609.     /* PutDimensionTags(struct Window *Reference,LONG Left,LONG Top,LONG Width,LONG Height):
  2610.      *
  2611.      *    Put back the default values for the requesters to open.
  2612.      */
  2613.  
  2614. VOID
  2615. PutDimensionTags(struct Window *Reference,LONG Left,LONG Top,LONG Width,LONG Height)
  2616. {
  2617.     if(Config -> MiscConfig -> RequesterMode != REQUESTERMODE_IGNORE && (!Config -> MiscConfig -> RequesterWidth || !Config -> MiscConfig -> RequesterHeight))
  2618.     {
  2619.         if(!Reference)
  2620.             Reference = Window;
  2621.  
  2622.         Config -> MiscConfig -> RequesterLeft    = Left    - Reference -> LeftEdge;
  2623.         Config -> MiscConfig -> RequesterTop    = Top    - Reference -> TopEdge;
  2624.         Config -> MiscConfig -> RequesterWidth    = Width;
  2625.         Config -> MiscConfig -> RequesterHeight    = Height;
  2626.     }
  2627. }
  2628.  
  2629.     /* GetDimensionTags(struct Window *Reference,struct TagItem *Tags):
  2630.      *
  2631.      *    Fills an array of tagitems with the dimensions of an asl requester
  2632.      *    to be opened.
  2633.      */
  2634.  
  2635. struct TagItem *
  2636. GetDimensionTags(struct Window *Reference,struct TagItem *Tags)
  2637. {
  2638.     if(Config -> MiscConfig -> RequesterMode == REQUESTERMODE_IGNORE || Config -> MiscConfig -> RequesterWidth < 1 || Config -> MiscConfig -> RequesterHeight < 1)
  2639.     {
  2640.         STATIC ULONG __aligned Done = TAG_DONE;
  2641.  
  2642.         return((struct TagItem *)&Done);
  2643.     }
  2644.     else
  2645.     {
  2646.         LONG Left,Top,Width,Height;
  2647.  
  2648.         if(!Reference)
  2649.             Reference = Window;
  2650.  
  2651.         if(Config -> MiscConfig -> RequesterMode == REQUESTERMODE_CENTRE)
  2652.         {
  2653.             Left    = Reference -> LeftEdge    + (Reference -> Width - Config -> MiscConfig -> RequesterWidth) / 2;
  2654.             Top    = Reference -> TopEdge    + (Reference -> Height - Config -> MiscConfig -> RequesterHeight) / 2;
  2655.         }
  2656.         else
  2657.         {
  2658.             Left    = Config -> MiscConfig -> RequesterLeft    + Reference -> LeftEdge;
  2659.             Top    = Config -> MiscConfig -> RequesterTop    + Reference -> TopEdge;
  2660.         }
  2661.  
  2662.         Width    = Config -> MiscConfig -> RequesterWidth;
  2663.         Height    = Config -> MiscConfig -> RequesterHeight;
  2664.  
  2665.         Tags[0] . ti_Tag    = ASL_LeftEdge;
  2666.         Tags[0] . ti_Data    = Left;
  2667.         Tags[1] . ti_Tag    = ASL_TopEdge;
  2668.         Tags[1] . ti_Data    = Top;
  2669.         Tags[2] . ti_Tag    = ASL_Width;
  2670.         Tags[2] . ti_Data    = Width;
  2671.         Tags[3] . ti_Tag    = ASL_Height;
  2672.         Tags[3] . ti_Data    = Height;
  2673.         Tags[4] . ti_Tag    = TAG_DONE;
  2674.  
  2675.         return(Tags);
  2676.     }
  2677. }
  2678.  
  2679.     /* GetFile(STRPTR Title,STRPTR Directory,STRPTR Name,STRPTR Buffer,STRPTR Pattern,BOOL SaveFlag,BOOL MultiSelect):
  2680.      *
  2681.      *    Call the asl.library file requester to select a single or
  2682.      *    a couple of files.
  2683.      */
  2684.  
  2685. struct FileRequester *
  2686. GetFile(struct Window *Parent,STRPTR Title,STRPTR Directory,STRPTR Name,STRPTR Buffer,STRPTR Pattern,BOOL SaveFlag,BOOL MultiSelect,BOOL DirsOnly,STRPTR OKText,BOOL AskWrite)
  2687. {
  2688.     STATIC UBYTE          DirBuffer[MAX_FILENAME_LENGTH],
  2689.                  PatternBuffer[60];
  2690.  
  2691.     struct FileRequester    *AslFileRequest;
  2692.     BOOL             Result        = FALSE,
  2693.                  DefaultPattern    = FALSE;
  2694.     LONG             Flags,ExtFlags = 0;
  2695.     LONG             i,j;
  2696.  
  2697.     UBYTE             OtherTitle[60];
  2698.     struct TagItem         DimensionTags[5];
  2699.  
  2700.     if(!Config -> MiscConfig -> ProtectiveMode)
  2701.         AskWrite = FALSE;
  2702.  
  2703.     if(!Parent)
  2704.         Parent = Window;
  2705.  
  2706.     for(i = j = 0 ; i < strlen(Title) ; i++)
  2707.     {
  2708.         if(Title[i] != '_')
  2709.             OtherTitle[j++] = Title[i];
  2710.     }
  2711.  
  2712.     OtherTitle[j] = 0;
  2713.  
  2714.     Title = OtherTitle;
  2715.  
  2716.     if(DirsOnly)
  2717.     {
  2718.         ExtFlags |= FIL1F_NOFILES;
  2719.  
  2720.         if(Pattern)
  2721.             ExtFlags |= FIL1F_MATCHDIRS;
  2722.     }
  2723.  
  2724.         /* Empty directory string? Revert to the last directory
  2725.          * name.
  2726.          */
  2727.  
  2728.     Forbid();
  2729.  
  2730.     if(!Directory[0])
  2731.     {
  2732.         if(!DirBuffer[0])
  2733.         {
  2734.             UBYTE LocalBuffer[MAX_FILENAME_LENGTH];
  2735.  
  2736.             if(!GetCurrentDirName(LocalBuffer,MAX_FILENAME_LENGTH))
  2737.                 LocalBuffer[0] = 0;
  2738.  
  2739.             if(!DirBuffer[0])
  2740.                 strcpy(DirBuffer,LocalBuffer);
  2741.         }
  2742.  
  2743.         Directory = DirBuffer;
  2744.     }
  2745.  
  2746.         /* If a wildcard pattern is required, add a gadget
  2747.          * to display it.
  2748.          */
  2749.  
  2750.     if(Pattern)
  2751.     {
  2752.         Flags = FILF_PATGAD;
  2753.  
  2754.         if(!Pattern[0])
  2755.         {
  2756.             DefaultPattern = TRUE;
  2757.  
  2758.             if(PatternBuffer[0])
  2759.                 Pattern = PatternBuffer;
  2760.             else
  2761.                 Pattern = "#?";
  2762.         }
  2763.         else
  2764.         {
  2765.             if(!Stricmp(Pattern,"#?") || !Stricmp(Pattern,PatternBuffer))
  2766.             {
  2767.                 DefaultPattern = TRUE;
  2768.  
  2769.                 Pattern = PatternBuffer;
  2770.             }
  2771.         }
  2772.     }
  2773.     else
  2774.     {
  2775.         Flags = 0;
  2776.  
  2777.         Pattern = "#?";
  2778.     }
  2779.  
  2780.     Permit();
  2781.  
  2782.         /* Set the save flag if we are about to save something. */
  2783.  
  2784.     if(SaveFlag)
  2785.         Flags |= FILF_SAVE;
  2786.  
  2787.         /* Set the multiselect bit if multiple files are
  2788.          * to be selected (e.g. for batch file upload).
  2789.          */
  2790.  
  2791.     if(MultiSelect)
  2792.         Flags |= FILF_MULTISELECT;
  2793.  
  2794.         /* Provide a standard `Ok' text if none
  2795.          * specified.
  2796.          */
  2797.  
  2798.     if(!OKText)
  2799.         OKText = (SaveFlag ? LocaleString(MSG_GLOBAL_SAVE_TXT) : LocaleString(MSG_GLOBAL_OPEN_TXT));
  2800.  
  2801.         /* Allocate the asl.library directory requester
  2802.          * and display it.
  2803.          */
  2804.  
  2805.     if(AslFileRequest = (struct FileRequester *)AllocAslRequestTags(ASL_FileRequest,
  2806.         ASLFR_Window,        Parent,
  2807.         ASLFR_InitialFile,    Name,
  2808.         ASLFR_InitialDrawer,    Directory,
  2809.         ASLFR_InitialPattern,    Pattern,
  2810.         ASLFR_PositiveText,    OKText,
  2811.         ASLFR_TextAttr,        &UserFont,
  2812.         ASLFR_PrivateIDCMP,    TRUE,
  2813.         ASLFR_Flags1,        Flags | FILF_NEWIDCMP,
  2814.         ASLFR_Flags2,        ExtFlags,
  2815.  
  2816.         Title ? ASLFR_TitleText : TAG_IGNORE,Title,
  2817.     TAG_MORE,GetDimensionTags(Parent,DimensionTags)))
  2818.     {
  2819.         LT_LockWindow(Parent);
  2820.  
  2821.         if(AslRequest(AslFileRequest,NULL))
  2822.         {
  2823.             PutDimensionTags(NULL,AslFileRequest -> fr_LeftEdge,AslFileRequest -> fr_TopEdge,AslFileRequest -> fr_Width,AslFileRequest -> fr_Height);
  2824.  
  2825.             if(!DirsOnly)
  2826.             {
  2827.                 STRPTR FileName;
  2828.  
  2829.                 if(AslFileRequest -> fr_NumArgs > 1 && AslFileRequest -> fr_ArgList)
  2830.                     FileName = AslFileRequest -> fr_ArgList -> wa_Name;
  2831.                 else
  2832.                     FileName = AslFileRequest -> fr_File;
  2833.  
  2834.                     /* Do we have a valid file name? */
  2835.  
  2836.                 if(FileName)
  2837.                 {
  2838.                         /* Build a legal path/file string. */
  2839.  
  2840.                     strcpy(Buffer,AslFileRequest -> fr_Drawer);
  2841.  
  2842.                     AddPart((STRPTR)Buffer,FileName,MAX_FILENAME_LENGTH);
  2843.  
  2844.                     Result = TRUE;
  2845.  
  2846.                     Forbid();
  2847.  
  2848.                     strcpy(DirBuffer,AslFileRequest -> fr_Drawer);
  2849.  
  2850.                     Permit();
  2851.                 }
  2852.             }
  2853.             else
  2854.             {
  2855.                 if(AslFileRequest -> fr_Drawer[0])
  2856.                 {
  2857.                     strcpy(Buffer,AslFileRequest -> fr_Drawer);
  2858.  
  2859.                     Result = TRUE;
  2860.  
  2861.                     Forbid();
  2862.  
  2863.                     strcpy(DirBuffer,AslFileRequest -> fr_Drawer);
  2864.  
  2865.                     Permit();
  2866.                 }
  2867.             }
  2868.         }
  2869.  
  2870.         LT_UnlockWindow(Parent);
  2871.     }
  2872.         /* We didn't get a file, no need to keep the
  2873.          * file requester.
  2874.          */
  2875.  
  2876.     if(!Result && AslFileRequest)
  2877.     {
  2878.         FreeAslRequest(AslFileRequest);
  2879.  
  2880.         return(NULL);
  2881.     }
  2882.     else
  2883.     {
  2884.         if(SaveFlag && AskWrite)
  2885.         {
  2886.             if(GetFileSize(Buffer))
  2887.             {
  2888.                 if(!ShowRequest(Parent,LocaleString(MSG_GLOBAL_FILE_ALREADY_EXISTS_OVERWRITE_TXT),LocaleString(MSG_GLOBAL_REPLACE_CANCEL_TXT),FilePart(Buffer)))
  2889.                 {
  2890.                     FreeAslRequest(AslFileRequest);
  2891.  
  2892.                     return(NULL);
  2893.                 }
  2894.             }
  2895.         }
  2896.  
  2897.         Forbid();
  2898.  
  2899.         if(DefaultPattern)
  2900.             strcpy(PatternBuffer,AslFileRequest -> fr_Pattern);
  2901.  
  2902.         Permit();
  2903.  
  2904.         return(AslFileRequest);
  2905.     }
  2906. }
  2907.  
  2908.     /* ShowRequest(struct Window *Window,STRPTR Text,STRPTR Gadgets,...):
  2909.      *
  2910.      *    Really quite simple varargs version of Intuition's
  2911.      *    EasyRequest requester.
  2912.      */
  2913.  
  2914. LONG __stdargs
  2915. ShowRequest(struct Window *Window,STRPTR Text,STRPTR Gadgets,...)
  2916. {
  2917.     struct EasyStruct    Easy;
  2918.     va_list            VarArgs;
  2919.     LONG            i,GadgetCount;
  2920.  
  2921.     for(i = GadgetCount = 0 ; i < strlen(Gadgets) ; i++)
  2922.     {
  2923.         if(Gadgets[i] == '|')
  2924.             GadgetCount++;
  2925.     }
  2926.  
  2927.         /* Standard data. */
  2928.  
  2929.     Easy . es_StructSize    = sizeof(struct EasyStruct);
  2930.     Easy . es_Flags        = NULL;
  2931.     Easy . es_Title        = LocaleString(MSG_TERMAUX_TERM_REQUEST_TXT);
  2932.     Easy . es_TextFormat    = Text;
  2933.     Easy . es_GadgetFormat    = Gadgets;
  2934.  
  2935.     if(GadgetCount)
  2936.     {
  2937.         LONG Result;
  2938.  
  2939.         if(GTLayoutBase)
  2940.             LT_LockWindow(Window);
  2941.  
  2942.             /* Use the argument array to build the
  2943.              * requester and display it.
  2944.              */
  2945.  
  2946.         va_start(VarArgs,Gadgets);
  2947.         Result = EasyRequestArgs(Window,&Easy,NULL,VarArgs);
  2948.         va_end(VarArgs);
  2949.  
  2950.         if(GTLayoutBase)
  2951.             LT_UnlockWindow(Window);
  2952.  
  2953.         return(Result);
  2954.     }
  2955.     else
  2956.     {
  2957.         struct Window *ReqWindow;
  2958.  
  2959.         if(GTLayoutBase)
  2960.             LT_LockWindow(Window);
  2961.  
  2962.         va_start(VarArgs,Gadgets);
  2963.  
  2964.         if(ReqWindow = BuildEasyRequestArgs(Window,&Easy,IDCMP_RAWKEY,VarArgs))
  2965.         {
  2966.             ULONG    IDCMP;
  2967.             LONG    Result;
  2968.  
  2969.             FOREVER
  2970.             {
  2971.                 WaitPort(ReqWindow -> UserPort);
  2972.  
  2973.                 IDCMP = NULL;
  2974.  
  2975.                 Result = SysReqHandler(ReqWindow,&IDCMP,FALSE);
  2976.  
  2977.                 if(!Result || (Result == -2 && !(IDCMP & IDCMP_RAWKEY)))
  2978.                     break;
  2979.             }
  2980.  
  2981.             FreeSysRequest(ReqWindow);
  2982.         }
  2983.  
  2984.         va_end(VarArgs);
  2985.  
  2986.         if(GTLayoutBase)
  2987.             LT_UnlockWindow(Window);
  2988.  
  2989.         return(0);
  2990.     }
  2991. }
  2992.  
  2993.     /* CloseWindowSafely(struct Window *Window):
  2994.      *
  2995.      *    Close a window freeing all messages pending at
  2996.      *    its user port (taken from example source code
  2997.      *    published once upon a time in Amiga Mail).
  2998.      */
  2999.  
  3000. VOID
  3001. CloseWindowSafely(struct Window *Window)
  3002. {
  3003.     Forbid();
  3004.  
  3005.     if(Window -> UserPort)
  3006.     {
  3007.         struct IntuiMessage    *IntuiMessage;
  3008.         struct Node        *Successor;
  3009.  
  3010.         IntuiMessage = (struct IntuiMessage *)Window -> UserPort -> mp_MsgList . lh_Head;
  3011.  
  3012.         while(Successor = IntuiMessage -> ExecMessage . mn_Node . ln_Succ)
  3013.         {
  3014.             if(IntuiMessage -> IDCMPWindow == Window)
  3015.             {
  3016.                 Remove(IntuiMessage);
  3017.  
  3018.                 ReplyMsg((struct Message *)IntuiMessage);
  3019.             }
  3020.  
  3021.             IntuiMessage = (struct IntuiMessage *)Successor;
  3022.         }
  3023.  
  3024.         Window -> UserPort = NULL;
  3025.     }
  3026.  
  3027.     ModifyIDCMP(Window,NULL);
  3028.  
  3029.     Permit();
  3030.  
  3031.     LT_DeleteWindowLock(Window);
  3032.  
  3033.     CloseWindow(Window);
  3034. }
  3035.  
  3036.     /* DelayTime(LONG Secs,LONG Micros):
  3037.      *
  3038.      *    Delay for a given period of time.
  3039.      */
  3040.  
  3041. VOID
  3042. DelayTime(LONG Secs,LONG Micros)
  3043. {
  3044.     StopTime();
  3045.  
  3046.     if(Secs || Micros)
  3047.     {
  3048.         StartTime(Secs,Micros);
  3049.  
  3050.         WaitTime();
  3051.     }
  3052. }
  3053.  
  3054.     /* WaitTime():
  3055.      *
  3056.      *    Wait for a pending time request to finish.
  3057.      */
  3058.  
  3059. VOID
  3060. WaitTime()
  3061. {
  3062.     if(TimerRunning)
  3063.     {
  3064.         TimerRunning = FALSE;
  3065.  
  3066.         WaitIO(TimeRequest);
  3067.     }
  3068. }
  3069.  
  3070.     /* StopTime():
  3071.      *
  3072.      *    Stop the running timer.
  3073.      */
  3074.  
  3075. VOID
  3076. StopTime()
  3077. {
  3078.     if(TimerRunning)
  3079.     {
  3080.         if(!CheckIO(TimeRequest))
  3081.             AbortIO(TimeRequest);
  3082.  
  3083.         WaitIO(TimeRequest);
  3084.     }
  3085. }
  3086.  
  3087.     /* StartTime(LONG Secs,LONG Micros):
  3088.      *
  3089.      *    Start the timer asynchronously.
  3090.      */
  3091.  
  3092. VOID
  3093. StartTime(LONG Secs,LONG Micros)
  3094. {
  3095.     StopTime();
  3096.  
  3097.     if(Secs || Micros)
  3098.     {
  3099.         TimeRequest->tr_node.io_Command    = TR_ADDREQUEST;
  3100.         TimeRequest->tr_time.tv_secs    = Secs;
  3101.         TimeRequest->tr_time.tv_micro    = Micros;
  3102.  
  3103.         ClrSignal(SIG_TIMER);
  3104.  
  3105.         SendIO(TimeRequest);
  3106.  
  3107.         TimerRunning = TRUE;
  3108.     }
  3109. }
  3110.  
  3111.     /* GetEnvDOS(STRPTR Name,STRPTR Buffer):
  3112.      *
  3113.      *    Get the contents of a vanilla AmigaDOS environment
  3114.      *    variable.
  3115.      */
  3116.  
  3117. STRPTR
  3118. GetEnvDOS(STRPTR Name,STRPTR Buffer)
  3119. {
  3120.     LONG    Size;
  3121.     BPTR    File,SomeLock;
  3122.  
  3123.     Buffer[0] = 0;
  3124.  
  3125.         /* Is ENV: present? */
  3126.  
  3127.     if(SomeLock = Lock("Env:",ACCESS_READ))
  3128.     {
  3129.         UBYTE SomeBuffer[MAX_FILENAME_LENGTH];
  3130.  
  3131.         UnLock(SomeLock);
  3132.  
  3133.         strcpy(SomeBuffer,"Env:");
  3134.         strcat(SomeBuffer,Name);
  3135.  
  3136.             /* Open the file. */
  3137.  
  3138.         if(File = Open(SomeBuffer,MODE_OLDFILE))
  3139.         {
  3140.                 /* Read the contents. */
  3141.  
  3142.             Size = Read(File,Buffer,256);
  3143.  
  3144.             Close(File);
  3145.  
  3146.             if(Size > 0)
  3147.             {
  3148.                 Buffer[Size] = 0;
  3149.  
  3150.                 return(Buffer);
  3151.             }
  3152.         }
  3153.     }
  3154.  
  3155.     return(NULL);
  3156. }
  3157.  
  3158.     /* SetEnvDOS(STRPTR Name,STRPTR Value):
  3159.      *
  3160.      *    Set the contents of a vanilla AmigaDOS environment
  3161.      *    variable.
  3162.      */
  3163.  
  3164. BOOL
  3165. SetEnvDOS(STRPTR Name,STRPTR Value)
  3166. {
  3167.     UBYTE    Buffer[MAX_FILENAME_LENGTH],*Destination;
  3168.     LONG    Length;
  3169.     BPTR    File,FileLock;
  3170.     BOOL    Success = TRUE;
  3171.     LONG    i;
  3172.  
  3173.     for(i = 0 ; i < 2 ; i++)
  3174.     {
  3175.         if(i)
  3176.             Destination = "EnvArc:";
  3177.         else
  3178.             Destination = "Env:";
  3179.  
  3180.             /* Is ENV:/ENVARC: present? */
  3181.  
  3182.         if(FileLock = Lock(Destination,ACCESS_READ))
  3183.         {
  3184.             UnLock(FileLock);
  3185.  
  3186.             strcpy(Buffer,Destination);
  3187.             strcat(Buffer,Name);
  3188.  
  3189.                 /* There already is a variable of that
  3190.                  * name in the environment storage
  3191.                  * directory.
  3192.                  */
  3193.  
  3194.             if(FileLock = Lock(Buffer,ACCESS_WRITE))
  3195.             {
  3196.                 UnLock(FileLock);
  3197.  
  3198.                     /* Delete the variable. */
  3199.  
  3200.                 if(!DeleteFile(Buffer))
  3201.                 {
  3202.                     Success = FALSE;
  3203.  
  3204.                     continue;
  3205.                 }
  3206.             }
  3207.  
  3208.                 /* Set the new variable. */
  3209.  
  3210.             if(Length = strlen(Value))
  3211.             {
  3212.                 if(File = Open(Buffer,MODE_NEWFILE))
  3213.                 {
  3214.                     if(Write(File,Value,Length) != Length)
  3215.                     {
  3216.                         Close(File);
  3217.  
  3218.                         DeleteFile(Buffer);
  3219.  
  3220.                         Success = FALSE;
  3221.                     }
  3222.                     else
  3223.                     {
  3224.                         Close(File);
  3225.  
  3226.                         AddProtection(Buffer,FIBF_EXECUTE);
  3227.                     }
  3228.                 }
  3229.                 else
  3230.                     Success = FALSE;
  3231.             }
  3232.         }
  3233.         else
  3234.             Success = FALSE;
  3235.     }
  3236.  
  3237.     return(Success);
  3238. }
  3239.  
  3240.     /* BumpWindow(struct Window *SomeWindow):
  3241.      *
  3242.      *    Bring a window to the front (and shift the screen
  3243.      *    back to its initial position).
  3244.      */
  3245.  
  3246. VOID
  3247. BumpWindow(struct Window *SomeWindow)
  3248. {
  3249.     if(SomeWindow)
  3250.     {
  3251.         if(SomeWindow -> WScreen -> LeftEdge > 0)
  3252.         {
  3253.             if(SomeWindow -> WScreen -> TopEdge > 0)
  3254.                 MoveScreen(SomeWindow -> WScreen,-SomeWindow -> WScreen -> LeftEdge,-SomeWindow -> WScreen -> TopEdge);
  3255.             else
  3256.                 MoveScreen(SomeWindow -> WScreen,-SomeWindow -> WScreen -> LeftEdge,0);
  3257.         }
  3258.         else
  3259.         {
  3260.             if(SomeWindow -> WScreen -> TopEdge > 0)
  3261.                 MoveScreen(SomeWindow -> WScreen,0,-SomeWindow -> WScreen -> TopEdge);
  3262.         }
  3263.  
  3264.         ScreenToFront(SomeWindow -> WScreen);
  3265.  
  3266.         ActivateWindow(SomeWindow);
  3267.     }
  3268. }
  3269.  
  3270.     /* PushWindow(struct Window *Window):
  3271.      *
  3272.      *    Push/PopWindow implement a single lifo window stack
  3273.      *    which always updates the window to activate when
  3274.      *    LSHIFT+RSHIFT+RETURN is pressed. This routine will
  3275.      *    push a window on the stack.
  3276.      */
  3277.  
  3278. VOID
  3279. PushWindow(struct Window *Window)
  3280. {
  3281.     if(WindowStackPtr < 5)
  3282.     {
  3283.         WindowStack[WindowStackPtr++] = Window;
  3284.  
  3285.         TopWindow = Window;
  3286.     }
  3287. }
  3288.  
  3289.     /* PopWindow():
  3290.      *
  3291.      *    Remove topmost window from window stack.
  3292.      */
  3293.  
  3294. VOID
  3295. PopWindow()
  3296. {
  3297.     if(WindowStackPtr > 0)
  3298.     {
  3299.         WindowStackPtr--;
  3300.  
  3301.         if(WindowStackPtr)
  3302.             TopWindow = WindowStack[WindowStackPtr - 1];
  3303.         else
  3304.             TopWindow = Window;
  3305.     }
  3306. }
  3307.  
  3308.     /* LoadMacros(STRPTR Name,struct MacroKeys *Keys):
  3309.      *
  3310.      *    Load the keyboard macros from a file.
  3311.      */
  3312.  
  3313. BOOL
  3314. LoadMacros(STRPTR Name,struct MacroKeys *Keys)
  3315. {
  3316.     struct IFFHandle    *Handle;
  3317.     BOOL             Success = FALSE;
  3318.     struct StoredProperty    *Prop;
  3319.     struct TermInfo        *TermInfo;
  3320.     LONG             Error;
  3321.  
  3322.     if(Handle = AllocIFF())
  3323.     {
  3324.         if(Handle -> iff_Stream = Open(Name,MODE_OLDFILE))
  3325.         {
  3326.             InitIFFasDOS(Handle);
  3327.  
  3328.             if(!(Error = OpenIFF(Handle,IFFF_READ)))
  3329.             {
  3330.                 /* Collect version number ID if
  3331.                  * available.
  3332.                  */
  3333.  
  3334.                 if(!(Error = PropChunks(Handle,(LONG *)VersionProps,1)))
  3335.                 {
  3336.                     /* The following line tells iffparse to stop at the
  3337.                      * very beginning of a `Type' chunk contained in a
  3338.                      * `TERM' FORM chunk.
  3339.                      */
  3340.  
  3341.                     if(!(Error = StopChunk(Handle,ID_TERM,ID_KEYS)))
  3342.                     {
  3343.                         /* Parse the file... */
  3344.  
  3345.                         if(!ParseIFF(Handle,IFFPARSE_SCAN))
  3346.                         {
  3347.                             /* Did we get a version ID? */
  3348.  
  3349.                             if(Prop = FindProp(Handle,ID_TERM,ID_VERS))
  3350.                             {
  3351.                                 TermInfo = (struct TermInfo *)Prop -> sp_Data;
  3352.  
  3353.                                 /* Is it the file format we are able
  3354.                                  * to read?
  3355.                                  */
  3356.  
  3357.                                 if((TermInfo -> Version > CONFIG_FILE_VERSION) || (TermInfo -> Version == CONFIG_FILE_VERSION && TermInfo -> Revision > CONFIG_FILE_REVISION) || (TermInfo -> Version == 1 && TermInfo -> Revision < 6))
  3358.                                 {
  3359.                                         /* Probably an older revision. */
  3360.  
  3361.                                     if(TermInfo -> Version == 1 && TermInfo -> Revision < 6)
  3362.                                     {
  3363.                                         memset(Keys,0,sizeof(struct MacroKeys));
  3364.  
  3365.                                         if(ReadChunkBytes(Handle,Keys,10 * 256) == 10 * 256)
  3366.                                             Success = TRUE;
  3367.                                         else
  3368.                                             Error = IoErr();
  3369.                                     }
  3370.                                     else
  3371.                                         Error = ERR_OUTDATED;
  3372.                                 }
  3373.                                 else
  3374.                                 {
  3375.                                     /* The file read pointer is positioned
  3376.                                      * just in front of the first data
  3377.                                      * to be read, so let's don't disappoint
  3378.                                      * iffparse and read it.
  3379.                                      */
  3380.  
  3381.                                     if(ReadChunkBytes(Handle,Keys,sizeof(struct MacroKeys)) == sizeof(struct MacroKeys))
  3382.                                         Success = TRUE;
  3383.                                     else
  3384.                                         Error = IoErr();
  3385.                                 }
  3386.                             }
  3387.                             else
  3388.                             {
  3389.                                     /* File was created by WriteIFFData previous
  3390.                                      * to revision 1.4.
  3391.                                      */
  3392.  
  3393.                                 memset(Keys,0,sizeof(struct MacroKeys));
  3394.  
  3395.                                 if(ReadChunkBytes(Handle,Keys,10 * 256) == 10 * 256)
  3396.                                     Success = TRUE;
  3397.                                 else
  3398.                                     Error = IoErr();
  3399.                             }
  3400.                         }
  3401.                     }
  3402.                 }
  3403.  
  3404.                 CloseIFF(Handle);
  3405.             }
  3406.  
  3407.             Close(Handle -> iff_Stream);
  3408.         }
  3409.         else
  3410.             Error = IoErr();
  3411.  
  3412.         FreeIFF(Handle);
  3413.     }
  3414.     else
  3415.         Error = ERR_NO_MEM;
  3416.  
  3417.     if(Error)
  3418.         SetIoErr(Error);
  3419.  
  3420.     return(Success);
  3421. }
  3422.  
  3423.     /* WriteIFFData(STRPTR Name,APTR Data,LONG Size,ULONG Type):
  3424.      *
  3425.      *    Write data to an IFF file (via iffparse.library).
  3426.      */
  3427.  
  3428. BOOL
  3429. WriteIFFData(STRPTR Name,APTR Data,LONG Size,ULONG Type)
  3430. {
  3431.     struct IFFHandle    *Handle;
  3432.     BOOL             Success = FALSE;
  3433.     LONG             Error;
  3434.  
  3435.         /* Allocate a handle. */
  3436.  
  3437.     if(Handle = AllocIFF())
  3438.     {
  3439.             /* Open an output stream. */
  3440.  
  3441.         if(Handle -> iff_Stream = Open(Name,MODE_NEWFILE))
  3442.         {
  3443.                 /* Tell iffparse that this is
  3444.                  * a DOS handle.
  3445.                  */
  3446.  
  3447.             InitIFFasDOS(Handle);
  3448.  
  3449.                 /* Open the handle for writing. */
  3450.  
  3451.             if(!(Error = OpenIFF(Handle,IFFF_WRITE)))
  3452.             {
  3453.                     /* Push outmost chunk onto stack. */
  3454.  
  3455.                 if(!(Error = PushChunk(Handle,ID_TERM,ID_FORM,IFFSIZE_UNKNOWN)))
  3456.                 {
  3457.                         /* Add a version identifier. */
  3458.  
  3459.                     if(!(Error = PushChunk(Handle,0,ID_VERS,IFFSIZE_UNKNOWN)))
  3460.                     {
  3461.                         struct TermInfo TermInfo;
  3462.  
  3463.                         TermInfo . Version    = CONFIG_FILE_VERSION;
  3464.                         TermInfo . Revision    = CONFIG_FILE_REVISION;
  3465.  
  3466.                             /* Write the version data. */
  3467.  
  3468.                         if(WriteChunkBytes(Handle,&TermInfo,sizeof(struct TermInfo)) == sizeof(struct TermInfo))
  3469.                         {
  3470.                                 /* Pop the version chunk, i.e. write it to the file. */
  3471.  
  3472.                             if(Error = PopChunk(Handle))
  3473.                                 Success = FALSE;
  3474.                             else
  3475.                             {
  3476.                                     /* Push the real data chunk on the stack. */
  3477.  
  3478.                                 if(!(Error = PushChunk(Handle,0,Type,IFFSIZE_UNKNOWN)))
  3479.                                 {
  3480.                                         /* Write the data. */
  3481.  
  3482.                                     if(WriteChunkBytes(Handle,Data,Size) == Size)
  3483.                                         Success = TRUE;
  3484.                                     else
  3485.                                         Error = IoErr();
  3486.  
  3487.                                             /* Pop the data chunk. */
  3488.  
  3489.                                     if(Success)
  3490.                                     {
  3491.                                         if(Error = PopChunk(Handle))
  3492.                                             Success = FALSE;
  3493.                                     }
  3494.                                 }
  3495.                                 else
  3496.                                     Success = FALSE;
  3497.                             }
  3498.                         }
  3499.                         else
  3500.                         {
  3501.                             Error = IoErr();
  3502.  
  3503.                             Success = FALSE;
  3504.                         }
  3505.                     }
  3506.  
  3507.                         /* Seems that we're done, now try to pop the FORM chunk
  3508.                          * and return.
  3509.                          */
  3510.  
  3511.                     if(Success)
  3512.                     {
  3513.                         if(Error = PopChunk(Handle))
  3514.                             Success = FALSE;
  3515.                     }
  3516.                 }
  3517.  
  3518.                     /* Close the handle (flush any pending data). */
  3519.  
  3520.                 CloseIFF(Handle);
  3521.             }
  3522.  
  3523.                 /* Close the DOS handle itself. */
  3524.  
  3525.             Close(Handle -> iff_Stream);
  3526.         }
  3527.         else
  3528.             Error = IoErr();
  3529.  
  3530.             /* And free the IFF handle. */
  3531.  
  3532.         FreeIFF(Handle);
  3533.     }
  3534.     else
  3535.         Error = ERR_NO_MEM;
  3536.  
  3537.     if(Success)
  3538.         AddProtection(Name,FIBF_EXECUTE);
  3539.  
  3540.     if(Error)
  3541.         SetIoErr(Error);
  3542.  
  3543.     return(Success);
  3544. }
  3545.  
  3546.     /* ReadIFFData(STRPTR Name,APTR Data,LONG Size,ULONG Type):
  3547.      *
  3548.      *    Read data from a `TERM' FORM chunk contained in an IFF file.
  3549.      */
  3550.  
  3551. BOOL
  3552. ReadIFFData(STRPTR Name,APTR Data,LONG Size,ULONG Type)
  3553. {
  3554.     struct IFFHandle    *Handle;
  3555.     BOOL             Success = FALSE;
  3556.     struct StoredProperty    *Prop;
  3557.     struct TermInfo        *TermInfo;
  3558.     LONG             Error = 0;
  3559.  
  3560.     if(Handle = AllocIFF())
  3561.     {
  3562.         if(Handle -> iff_Stream = Open(Name,MODE_OLDFILE))
  3563.         {
  3564.             InitIFFasDOS(Handle);
  3565.  
  3566.             if(!(Error = OpenIFF(Handle,IFFF_READ)))
  3567.             {
  3568.                 /* Collect version number ID if
  3569.                  * available.
  3570.                  */
  3571.  
  3572.                 if(!(Error = PropChunks(Handle,(LONG *)VersionProps,1)))
  3573.                 {
  3574.                     /* The following line tells iffparse to stop at the
  3575.                      * very beginning of a `Type' chunk contained in a
  3576.                      * `TERM' FORM chunk.
  3577.                      */
  3578.  
  3579.                     if(!(Error = StopChunk(Handle,ID_TERM,Type)))
  3580.                     {
  3581.                         /* Parse the file... */
  3582.  
  3583.                         if(!ParseIFF(Handle,IFFPARSE_SCAN))
  3584.                         {
  3585.                             /* Did we get a version ID? */
  3586.  
  3587.                             if(Prop = FindProp(Handle,ID_TERM,ID_VERS))
  3588.                             {
  3589.                                 TermInfo = (struct TermInfo *)Prop -> sp_Data;
  3590.  
  3591.                                 /* Is it the file format we are able
  3592.                                  * to read?
  3593.                                  */
  3594.  
  3595.                                 if((TermInfo -> Version > CONFIG_FILE_VERSION) || (TermInfo -> Version == CONFIG_FILE_VERSION && TermInfo -> Revision > CONFIG_FILE_REVISION) || (TermInfo -> Version == 1 && TermInfo -> Revision < 6))
  3596.                                 {
  3597.                                     Error = ERR_OUTDATED;
  3598.  
  3599.                                     Success = FALSE;
  3600.                                 }
  3601.                                 else
  3602.                                 {
  3603.                                     struct ContextNode *Chunk = CurrentChunk(Handle);
  3604.  
  3605.                                     if(Chunk -> cn_Size < Size)
  3606.                                         Size = Chunk -> cn_Size;
  3607.  
  3608.                                     /* The file read pointer is positioned
  3609.                                      * just in front of the first data
  3610.                                      * to be read, so let's don't disappoint
  3611.                                      * iffparse and read it.
  3612.                                      */
  3613.  
  3614.                                     if(ReadChunkBytes(Handle,Data,Size) == Size)
  3615.                                         Success = TRUE;
  3616.                                     else
  3617.                                         Error = IoErr();
  3618.                                 }
  3619.                             }
  3620.                         }
  3621.                     }
  3622.                 }
  3623.  
  3624.                 CloseIFF(Handle);
  3625.             }
  3626.  
  3627.             Close(Handle -> iff_Stream);
  3628.         }
  3629.         else
  3630.             Error = IoErr();
  3631.  
  3632.         FreeIFF(Handle);
  3633.     }
  3634.  
  3635.     if(Error)
  3636.         SetIoErr(Error);
  3637.  
  3638.     return(Success);
  3639. }
  3640.  
  3641.     /* SplitFileName():
  3642.      *
  3643.      *    Split a full file name into a file and a drawer name.
  3644.      */
  3645.  
  3646. VOID
  3647. SplitFileName(STRPTR FullName,STRPTR *FileName,STRPTR DrawerName)
  3648. {
  3649.     if(FilePart(FullName) == FullName)
  3650.     {
  3651.         *DrawerName    = 0;
  3652.         *FileName    = FullName;
  3653.     }
  3654.     else
  3655.     {
  3656.         STRPTR Dummy;
  3657.  
  3658.         strcpy(DrawerName,FullName);
  3659.  
  3660.         Dummy = PathPart(DrawerName);
  3661.  
  3662.         *Dummy = 0;
  3663.  
  3664.         *FileName = FilePart(FullName);
  3665.     }
  3666. }
  3667.  
  3668.     /* CreateList():
  3669.      *
  3670.      *    Create a small, empty list.
  3671.      */
  3672.  
  3673. struct List *
  3674. CreateList()
  3675. {
  3676.     struct List *List;
  3677.  
  3678.     if(List = (struct List *)AllocVecPooled(sizeof(struct MinList),MEMF_ANY))
  3679.         NewList(List);
  3680.  
  3681.     return(List);
  3682. }
  3683.  
  3684.     /* DeleteList():
  3685.      *
  3686.      *    Free the contents of a list and the list itself.
  3687.      */
  3688.  
  3689. VOID
  3690. DeleteList(struct List *List)
  3691. {
  3692.     if(List)
  3693.     {
  3694.         struct Node    *Node,
  3695.                 *Next;
  3696.  
  3697.         for(Node = List -> lh_Head ; Next = Node -> ln_Succ ; Node = Next)
  3698.             FreeVecPooled(Node);
  3699.  
  3700.         FreeVecPooled(List);
  3701.     }
  3702. }
  3703.  
  3704.     /* BackfillRoutine():
  3705.      *
  3706.      *    Window layer backfill routine.
  3707.      */
  3708.  
  3709. VOID __saveds __asm
  3710. BackfillRoutine(REG(a0) struct Hook *Hook,REG(a1) LayerMsg *Bounds,REG(a2) struct RastPort *RPort)
  3711. {
  3712.     struct RastPort RastPort;
  3713.  
  3714.     InitRastPort(&RastPort);
  3715.  
  3716.     RastPort.BitMap = RPort->BitMap;
  3717.  
  3718.     RPort = &RastPort;
  3719.  
  3720.     SetAPen(RPort,Pens[BACKGROUNDPEN]);
  3721.  
  3722.     RectFill(RPort,Bounds->Bounds.MinX,Bounds->Bounds.MinY,Bounds->Bounds.MaxX,Bounds->Bounds.MaxY);
  3723. }
  3724.  
  3725. struct NameSegment
  3726. {
  3727.     UBYTE    String[63],
  3728.         Separator;
  3729. };
  3730.  
  3731. STATIC STRPTR
  3732. FindChar(STRPTR Template,LONG c)
  3733. {
  3734.     while(*Template)
  3735.     {
  3736.         if(*Template == c)
  3737.             return(Template);
  3738.         else
  3739.             Template++;
  3740.     }
  3741.  
  3742.     return(NULL);
  3743. }
  3744.  
  3745. STATIC UBYTE *
  3746. GetNameSegment(struct NameSegment *NameSegment,UBYTE *cp,LONG i)
  3747. {
  3748.     UBYTE *xp = NameSegment[i] . String;
  3749.  
  3750.     while (*cp && !FindChar("._+-,@~=",*cp))
  3751.         *xp++ = *cp++;
  3752.  
  3753.     *xp = '\0';
  3754.  
  3755.     NameSegment[i] . Separator = *cp;
  3756.  
  3757.     if (*cp)
  3758.         cp++;
  3759.  
  3760.     if(NameSegment[i] . String[0] || NameSegment[i] . Separator)
  3761.         return(cp);
  3762.     else
  3763.         return(NULL);
  3764. }
  3765.  
  3766. STATIC VOID
  3767. CopyNameSegment(struct NameSegment *NameSegment,UBYTE *Destination,LONG Zap)
  3768. {
  3769.     UBYTE *cp = Destination,*xp;
  3770.  
  3771.     for(xp = NameSegment[0] . String ; *xp ; )
  3772.         *cp++ = *xp++;
  3773.  
  3774.     if(NameSegment[0] . Separator)
  3775.     {
  3776.         register LONG i;
  3777.  
  3778.         *cp++ = NameSegment[0] . Separator;
  3779.  
  3780.         for(i = Zap + 1 ; ; i++)
  3781.         {
  3782.             for(xp = NameSegment[i] . String ; *xp ; )
  3783.                 *cp++ = *xp++;
  3784.  
  3785.             if(NameSegment[i] . Separator)
  3786.                 *cp++ = NameSegment[i] . Separator;
  3787.             else
  3788.             {
  3789.                 if(!NameSegment[i] . String[0])
  3790.                     break;
  3791.             }
  3792.         }
  3793.     }
  3794.  
  3795.     *cp = 0;
  3796. }
  3797.  
  3798.     /* ShrinkName():
  3799.      *
  3800.      *    Shrink a file name down to a number of characters, if
  3801.      *    possible preserving the structure of the name. Algorithm
  3802.      *    courtesy of the "shrink" program by Simon Brown,
  3803.      *    Edinburgh University.
  3804.      */
  3805.  
  3806. UBYTE *
  3807. ShrinkName(const UBYTE *Source,UBYTE *Destination,LONG MaxLength,BOOL FixSuffix)
  3808. {
  3809.     #define MAXSEGS 10
  3810.  
  3811.     struct NameSegment NameSegment[MAXSEGS];
  3812.  
  3813.     LONG i,NumSegments,SuffixLength,Remainder,Delete,Total,Zap = 0;
  3814.     UBYTE *OldPtr = (UBYTE *)Source;
  3815.  
  3816.     for(i = 0 ; i < MAXSEGS && (OldPtr = GetNameSegment(NameSegment,OldPtr,i)) ; i++);
  3817.  
  3818.     if(i < MAXSEGS)
  3819.     {
  3820.         NumSegments = i - 1;
  3821.  
  3822.         if((NumSegments * 2) < MaxLength)
  3823.         {
  3824.             SuffixLength = strlen(NameSegment[NumSegments] . String);
  3825.  
  3826.             if(SuffixLength > MaxLength - NumSegments - 1)
  3827.             {
  3828.                 SuffixLength = MaxLength - (2 * NumSegments) - 1;
  3829.  
  3830.                 NameSegment[NumSegments] . String[SuffixLength - 1] = 0;
  3831.             }
  3832.             else
  3833.             {
  3834.                 if (SuffixLength + NumSegments > MaxLength-NumSegments-1)
  3835.                     Zap = NumSegments - (MaxLength-SuffixLength)/2;
  3836.             }
  3837.  
  3838.             if(NumSegments >= 1)
  3839.             {
  3840.                 for(i = Zap + 1 ; i <= NumSegments ; i++)
  3841.                 {
  3842.                     if(NameSegment[i] . Separator)
  3843.                         SuffixLength++;
  3844.                 }
  3845.  
  3846.                 if(NameSegment[0] . Separator)
  3847.                     SuffixLength++;
  3848.  
  3849.                 Remainder = MaxLength - SuffixLength;
  3850.  
  3851.                 Delete = Remainder / NumSegments;
  3852.  
  3853.                 Total = SuffixLength;
  3854.  
  3855.                 for(i = Zap + 1 ; i < NumSegments ; i++)
  3856.                 {
  3857.                     NameSegment[i] . String[Delete] = 0;
  3858.  
  3859.                     Total += Delete;
  3860.                 }
  3861.  
  3862.                 NameSegment[0] . String[MaxLength - Total] = 0;
  3863.             }
  3864.  
  3865.             CopyNameSegment(NameSegment,Destination,Zap);
  3866.         }
  3867.         else
  3868.             strcpy(Destination,Source);
  3869.     }
  3870.     else
  3871.         strcpy(Destination,Source);
  3872.  
  3873.     if(FixSuffix)
  3874.     {
  3875.         BOOL    GotDot    = FALSE;
  3876.         LONG    Len    = strlen(Destination),Dots;
  3877.  
  3878.         for(i = Dots = 0 ; i < Len ; i++)
  3879.         {
  3880.             if(Destination[i] == '.')
  3881.                 Dots++;
  3882.         }
  3883.  
  3884.         if(!Dots)
  3885.         {
  3886.             if(Len < 4)
  3887.                 strcat(Destination,".___");
  3888.             else
  3889.                 Destination[Len - 4] = '.';
  3890.         }
  3891.  
  3892.         for(i = Len - 1 ; i >= 0 ; i--)
  3893.         {
  3894.             if(Destination[i] == '.')
  3895.             {
  3896.                 if(GotDot)
  3897.                     Destination[i] = '_';
  3898.                 else
  3899.                     GotDot = TRUE;
  3900.             }
  3901.  
  3902.             if(Destination[i] == '\\')
  3903.                 Destination[i] = '-';
  3904.         }
  3905.     }
  3906.  
  3907.     return(Destination);
  3908. }
  3909.  
  3910.     /* BuildFontName(STRPTR Destination,const STRPTR Name,LONG Size):
  3911.      *
  3912.      *    Build a font name and size string from given
  3913.      *    information (raw name and size).
  3914.      */
  3915.  
  3916. VOID
  3917. BuildFontName(STRPTR Destination,const STRPTR Name,LONG Size)
  3918. {
  3919.     UBYTE    LocalBuffer[50];
  3920.     LONG    Len;
  3921.  
  3922.     strcpy(LocalBuffer,FilePart((STRPTR)Name));
  3923.  
  3924.     Len = strlen(LocalBuffer);
  3925.  
  3926.     if(Len > 5)
  3927.     {
  3928.         if(!Stricmp(&LocalBuffer[Len - 5],".font"))
  3929.             LocalBuffer[Len - 5] = 0;
  3930.     }
  3931.  
  3932.     SPrintf(Destination,"%s %ld",LocalBuffer,Size);
  3933. }
  3934.  
  3935.     /* CreateMenuGlyphs():
  3936.      *
  3937.      *    Create scaled glyphs for pull-down menus.
  3938.      */
  3939.  
  3940. BOOL
  3941. CreateMenuGlyphs(struct Screen *Screen,struct DrawInfo *DrawInfo,struct Image **AmigaPtr,struct Image **CheckPtr)
  3942. {
  3943.     struct Image    *AmigaGlyph,
  3944.             *CheckGlyph;
  3945.     LONG         AspectX,AspectY,
  3946.              Size,FontHeight;
  3947.  
  3948.     FontHeight = DrawInfo -> dri_Font -> tf_Baseline + 2;
  3949.  
  3950.     if(Screen -> Flags & SCREENHIRES)
  3951.         Size = SYSISIZE_MEDRES;
  3952.     else
  3953.         Size = SYSISIZE_LOWRES;
  3954.  
  3955.     AspectX = DrawInfo -> dri_Resolution . X;
  3956.     AspectY = DrawInfo -> dri_Resolution . Y;
  3957.  
  3958.     if(AmigaGlyph = NewObject(NULL,SYSICLASS,
  3959.         SYSIA_DrawInfo,    DrawInfo,
  3960.         SYSIA_Size,    Size,
  3961.         SYSIA_Which,    AMIGAKEY,
  3962.         IA_Left,    0,
  3963.         LA_Top,        0,
  3964.         IA_Width,    (FontHeight * 3 * AspectY) / (2 * AspectX),
  3965.         IA_Height,    FontHeight,
  3966.     TAG_DONE))
  3967.     {
  3968.         if(!(CheckGlyph = NewObject(NULL,SYSICLASS,
  3969.             SYSIA_DrawInfo,    DrawInfo,
  3970.             SYSIA_Size,    Size,
  3971.             SYSIA_Which,    MENUCHECK,
  3972.             IA_Left,    0,
  3973.             LA_Top,        0,
  3974.             IA_Width,    (FontHeight * AspectY) / AspectX,
  3975.             IA_Height,    FontHeight,
  3976.         TAG_DONE)))
  3977.         {
  3978.             DisposeObject(AmigaGlyph);
  3979.  
  3980.             AmigaGlyph = NULL;
  3981.         }
  3982.     }
  3983.  
  3984.     if(AmigaGlyph && CheckGlyph)
  3985.     {
  3986.         *AmigaPtr = AmigaGlyph;
  3987.         *CheckPtr = CheckGlyph;
  3988.  
  3989.         return(TRUE);
  3990.     }
  3991.     else
  3992.         return(FALSE);
  3993. }
  3994.  
  3995.     /* FixName(STRPTR Name):
  3996.      *
  3997.      *    Build a correct AmigaDOS filename.
  3998.      */
  3999.  
  4000. VOID
  4001. FixName(STRPTR Name)
  4002. {
  4003.     LONG    NameLen    = strlen(Name),
  4004.         i;
  4005.  
  4006.         /* Replace special characters. */
  4007.  
  4008.     for(i = 0 ; i < NameLen ; i++)
  4009.     {
  4010.         switch(Name[i])
  4011.         {
  4012.             case ' ':
  4013.  
  4014.                 Name[i] = '_';
  4015.                 break;
  4016.  
  4017.             case ':':
  4018.  
  4019.                 Name[i] = '.';
  4020.                 break;
  4021.  
  4022.             case '/':
  4023.  
  4024.                 Name[i] = '\\';
  4025.                 break;
  4026.  
  4027.             case '\"':
  4028.  
  4029.                 Name[i] = '\'';
  4030.                 break;
  4031.         }
  4032.     }
  4033.  
  4034.         /* Truncate the name. */
  4035.  
  4036.     if(NameLen > 31)
  4037.         Name[31] = 0;
  4038. }
  4039.  
  4040.     /* ShowError(struct Window *Window,LONG Primary,LONG Secondary,STRPTR String):
  4041.      *
  4042.      *    Display an error message, in human readable form if possible.
  4043.      */
  4044.  
  4045. VOID
  4046. ShowError(struct Window *Window,LONG Primary,LONG Secondary,STRPTR String)
  4047. {
  4048.     STATIC LONG LocalErrors[][2] =
  4049.     {
  4050.         ERR_SAVE_ERROR,            MSG_ERR_COULD_NOT_SAVE_FILE_TXT,
  4051.         ERR_LOAD_ERROR,            MSG_ERR_COULD_NOT_LOAD_FILE_TXT,
  4052.         ERR_NO_MEM,            MSG_ERR_NO_MEM_TXT,
  4053.         ERR_OUTDATED,            MSG_ERR_OUTDATED_TXT,
  4054.         ERR_EXECUTE_ERROR,        MSG_ERR_COULD_NOT_EXECUTE_PROGRAM_TXT,
  4055.  
  4056.         ERR_FILE_NOT_FOUND,        MSG_VERIFY_NO_FILE_TXT,
  4057.         ERR_DRAWER_NOT_FOUND,        MSG_VERIFY_DRAWER_NOT_FOUND_TXT,
  4058.         ERR_PROGRAM_NOT_FOUND,        MSG_VERIFY_NO_PROGRAM_TXT,
  4059.         ERR_NOT_A_FILE,            MSG_VERIFY_DRAWER_NOT_A_FILE_TXT,
  4060.         ERR_NOT_A_DRAWER,        MSG_VERIFY_FILE_NOT_A_DRAWER_TXT,
  4061.  
  4062.         IFFERR_NOMEM,            MSG_IFFERR_NOMEM_TXT,
  4063.         IFFERR_READ,            MSG_IFFERR_READ_TXT,
  4064.         IFFERR_WRITE,            MSG_IFFERR_WRITE_TXT,
  4065.         IFFERR_SEEK,            MSG_IFFERR_SEEK_TXT,
  4066.         IFFERR_MANGLED,            MSG_IFFERR_MANGLED_TXT,
  4067.         IFFERR_NOTIFF,            MSG_IFFERR_NOTIFF_TXT,
  4068.  
  4069.         0,                0
  4070.     };
  4071.  
  4072.     STRPTR    PrimaryError    = NULL,
  4073.         SecondaryError    = NULL;
  4074.  
  4075.     if(Primary)
  4076.     {
  4077.         LONG i;
  4078.  
  4079.         for(i = 0 ; LocalErrors[i][0] ; i++)
  4080.         {
  4081.             if(LocalErrors[i][0] == Primary)
  4082.             {
  4083.                 PrimaryError = LocaleString(LocalErrors[i][1]);
  4084.  
  4085.                 break;
  4086.             }
  4087.         }
  4088.  
  4089.         if(!PrimaryError)
  4090.         {
  4091.             STATIC UBYTE Buffer[256];
  4092.  
  4093.             Fault(Primary,"",Buffer,256);
  4094.  
  4095.             PrimaryError = Buffer + 2;
  4096.         }
  4097.     }
  4098.  
  4099.     if(Secondary)
  4100.     {
  4101.         LONG i;
  4102.  
  4103.         for(i = 0 ; LocalErrors[i][0] ; i++)
  4104.         {
  4105.             if(LocalErrors[i][0] == Secondary)
  4106.             {
  4107.                 SecondaryError = LocaleString(LocalErrors[i][1]);
  4108.  
  4109.                 break;
  4110.             }
  4111.         }
  4112.  
  4113.         if(!SecondaryError)
  4114.         {
  4115.             STATIC UBYTE Buffer[256];
  4116.  
  4117.             Fault(Secondary,"",Buffer,256);
  4118.  
  4119.             SecondaryError = Buffer + 2;
  4120.         }
  4121.     }
  4122.  
  4123.     if(PrimaryError)
  4124.     {
  4125.         if(String)
  4126.             ShowRequest(Window,PrimaryError,LocaleString(MSG_GLOBAL_CONTINUE_TXT),String,SecondaryError);
  4127.         else
  4128.             ShowRequest(Window,PrimaryError,LocaleString(MSG_GLOBAL_CONTINUE_TXT),SecondaryError);
  4129.     }
  4130. }
  4131.  
  4132. struct RendezvousData * __saveds __asm
  4133. RendezvousLogin(REG(a0) struct MsgPort *ReadPort,REG(a1) struct MsgPort *WritePort,REG(a2) struct TagItem *TagList)
  4134. {
  4135.     struct RendezvousData *Data;
  4136.  
  4137.     if(Data = (struct RendezvousData *)AllocVecPooled(sizeof(struct RendezvousData),MEMF_ANY | MEMF_CLEAR))
  4138.     {
  4139.         struct DataMsg Msg;
  4140.  
  4141.         InitMsgItem(&Msg,TaskDestructor);
  4142.  
  4143.         Msg . Type = DATAMSGTYPE_RENDEZVOUS;
  4144.         Msg . Data = (UBYTE *)FindTask(NULL);
  4145.  
  4146.         Forbid();
  4147.  
  4148.         ClrSignal(SIGBREAKF_CTRL_F);
  4149.  
  4150.         PutMsgItem(SpecialQueue,(struct MsgItem *)&Msg);
  4151.  
  4152.         Wait(SIGBREAKF_CTRL_F);
  4153.  
  4154.         Permit();
  4155.  
  4156.         if(ReadRequest && WriteRequest)
  4157.         {
  4158.             struct List *UploadList;
  4159.  
  4160.             CopyMem(ReadRequest,&Data -> rd_ReadRequest,sizeof(struct IOExtSer));
  4161.  
  4162.             Data -> rd_ReadRequest . IOSer . io_Message . mn_ReplyPort = ReadPort;
  4163.  
  4164.             CopyMem(WriteRequest,&Data -> rd_WriteRequest,sizeof(struct IOExtSer));
  4165.  
  4166.             Data -> rd_WriteRequest . IOSer . io_Message . mn_ReplyPort = WritePort;
  4167.  
  4168.             if(Window)
  4169.                 Data -> rd_Screen = Window -> WScreen;
  4170.  
  4171.             NewList(&Data -> rd_UploadList);
  4172.             NewList(&Data -> rd_DownloadList);
  4173.             NewList(&Data -> rd_SentList);
  4174.             NewList(&Data -> rd_ReceivedList);
  4175.  
  4176.             if(UploadList = GetUploadList())
  4177.             {
  4178.                 struct Node *Node,*Next;
  4179.  
  4180.                 for(Node = UploadList -> lh_Head ; Next = Node -> ln_Succ ; Node = Next)
  4181.                     AddTail(&Data -> rd_UploadList,Node);
  4182.  
  4183.                 FreeVecPooled(UploadList);
  4184.             }
  4185.  
  4186.             Data -> rd_SendPath    = Config -> PathConfig -> BinaryUploadPath;
  4187.             Data -> rd_ReceivePath    = Config -> PathConfig -> BinaryDownloadPath;
  4188.             Data -> rd_Options    = "";
  4189.         }
  4190.         else
  4191.         {
  4192.             FreeVecPooled(Data);
  4193.  
  4194.             Data = NULL;
  4195.         }
  4196.     }
  4197.  
  4198.     return(Data);
  4199. }
  4200.  
  4201. VOID __saveds __asm
  4202. RendezvousLogoff(REG(a0) struct RendezvousData *Data)
  4203. {
  4204.     if(Data)
  4205.     {
  4206.         struct Node *Node,*Next;
  4207.  
  4208.         for(Node = Data -> rd_UploadList . lh_Head ; Next = Node -> ln_Succ ; Node = Next)
  4209.             FreeVecPooled(Node);
  4210.  
  4211.         for(Node = Data -> rd_DownloadList . lh_Head ; Next = Node -> ln_Succ ; Node = Next)
  4212.             FreeVecPooled(Node);
  4213.  
  4214.         for(Node = Data -> rd_SentList . lh_Head ; Next = Node -> ln_Succ ; Node = Next)
  4215.             FreeVecPooled(Node);
  4216.  
  4217.         for(Node = Data -> rd_ReceivedList . lh_Head ; Next = Node -> ln_Succ ; Node = Next)
  4218.             FreeVecPooled(Node);
  4219.  
  4220.         FreeVecPooled(Data);
  4221.  
  4222.         Signal(ThisProcess,SIG_HANDSHAKE);
  4223.     }
  4224. }
  4225.  
  4226. struct Node * __saveds __asm
  4227. RendezvousNewNode(REG(a0) STRPTR Name)
  4228. {
  4229.     if(Name)
  4230.     {
  4231.         LONG Len;
  4232.  
  4233.         if(Len = strlen(Name))
  4234.         {
  4235.             struct Node *Node;
  4236.  
  4237.             if(Node = (struct Node *)AllocVecPooled(sizeof(struct Node) + Len + 1,MEMF_ANY))
  4238.             {
  4239.                 memset(Node,0,sizeof(struct Node));
  4240.  
  4241.                 strcpy(Node -> ln_Name = (STRPTR)(Node + 1),Name);
  4242.  
  4243.                 return(Node);
  4244.             }
  4245.         }
  4246.     }
  4247.  
  4248.     return(NULL);
  4249. }
  4250.  
  4251. struct List *
  4252. BuildModeList(LONG *Index,ULONG DisplayMode,ULONG (* __asm ModeFilter)(REG(d0) ULONG ID,REG(a0) APTR UserData),APTR UserData)
  4253. {
  4254.     struct List    *List;
  4255.     LONG         Count = 0;
  4256.  
  4257.     *Index = 0;
  4258.  
  4259.     if(List = (struct List *)AllocVecPooled(sizeof(struct MinList),MEMF_ANY))
  4260.     {
  4261.         struct DisplayInfo    DisplayInfo;
  4262.         ULONG            SomeMode = INVALID_ID;
  4263.  
  4264.         NewList(List);
  4265.  
  4266.         while((SomeMode = NextDisplayInfo(SomeMode)) != INVALID_ID)
  4267.         {
  4268.             if(GetDisplayInfoData(NULL,(APTR)&DisplayInfo,sizeof(struct DisplayInfo),DTAG_DISP,SomeMode))
  4269.             {
  4270.                 if((DisplayInfo . PropertyFlags & DIPF_IS_WB) && !(DisplayInfo . NotAvailable & ~DI_AVAIL_NOTWITHGENLOCK))
  4271.                 {
  4272.                     STRPTR Name;
  4273.  
  4274.                     if(ModeFilter)
  4275.                     {
  4276.                         if(!(*ModeFilter)(SomeMode,UserData))
  4277.                             continue;
  4278.                     }
  4279.  
  4280.                     if(Name = GetModeName(SomeMode))
  4281.                     {
  4282.                         struct ModeNode    *ModeNode;
  4283.  
  4284.                         if(ModeNode = (struct ModeNode *)AllocVecPooled(sizeof(struct ModeNode) + strlen(Name) + 1,MEMF_ANY))
  4285.                         {
  4286.                             ModeNode -> VanillaNode . ln_Name = (STRPTR)(ModeNode + 1);
  4287.  
  4288.                             strcpy(ModeNode -> VanillaNode . ln_Name,Name);
  4289.  
  4290.                             ModeNode -> DisplayID = SomeMode;
  4291.  
  4292.                             AddTail(List,ModeNode);
  4293.  
  4294.                             Count++;
  4295.                         }
  4296.                     }
  4297.                 }
  4298.             }
  4299.         }
  4300.     }
  4301.  
  4302.     if(Count)
  4303.     {
  4304.         struct ModeNode    *Node,
  4305.                 *Next;
  4306.  
  4307.         for(Node = (struct ModeNode *)List -> lh_Head ; Node -> VanillaNode . ln_Succ ; Node = (struct ModeNode *)Node -> VanillaNode . ln_Succ)
  4308.         {
  4309.             if(!(Node -> DisplayID & MONITOR_ID_MASK))
  4310.             {
  4311.                 for(Next = (struct ModeNode *)List -> lh_Head ; Next -> VanillaNode . ln_Succ ; Next = (struct ModeNode *)Next -> VanillaNode . ln_Succ)
  4312.                 {
  4313.                     if((Node -> DisplayID & ~MONITOR_ID_MASK) == (Next -> DisplayID & ~MONITOR_ID_MASK) && Next != Node)
  4314.                         Node -> DisplayID = INVALID_ID;
  4315.                 }
  4316.             }
  4317.  
  4318.             for(Next = (struct ModeNode *)List -> lh_Head ; Next -> VanillaNode . ln_Succ ; Next = (struct ModeNode *)Next -> VanillaNode . ln_Succ)
  4319.             {
  4320.                 if(Node -> DisplayID == Next -> DisplayID && Next != Node)
  4321.                     Next -> DisplayID = INVALID_ID;
  4322.             }
  4323.         }
  4324.  
  4325.         for(Node = (struct ModeNode *)List -> lh_Head ; Next = (struct ModeNode *)Node -> VanillaNode . ln_Succ ; Node = Next)
  4326.         {
  4327.             if(Node -> DisplayID == INVALID_ID)
  4328.             {
  4329.                 Count--;
  4330.  
  4331.                 Remove(Node);
  4332.  
  4333.                 FreeVecPooled(Node);
  4334.             }
  4335.         }
  4336.     }
  4337.  
  4338.     if(Count)
  4339.     {
  4340.         struct ModeNode    *Node,
  4341.                 *Next;
  4342.  
  4343.         for(Count = 0, Node = (struct ModeNode *)List -> lh_Head ; Next = (struct ModeNode *)Node -> VanillaNode . ln_Succ ; Node = Next)
  4344.         {
  4345.             if(Node -> DisplayID == DisplayMode)
  4346.             {
  4347.                 *Index = Count;
  4348.  
  4349.                 break;
  4350.             }
  4351.         }
  4352.  
  4353.         return(List);
  4354.     }
  4355.     else
  4356.     {
  4357.         DeleteList(List);
  4358.  
  4359.         return(NULL);
  4360.     }
  4361. }
  4362.  
  4363.     /* IsAssign(STRPTR Name):
  4364.      *
  4365.      *    Does a name refer to an assignment?
  4366.      */
  4367.  
  4368. BOOL
  4369. IsAssign(STRPTR Name)
  4370. {
  4371.     LONG NameLen    = strlen(Name) - 1;
  4372.     BOOL Result    = FALSE;
  4373.  
  4374.         /* Does it end with a colon? */
  4375.  
  4376.     if(Name[NameLen] == ':')
  4377.     {
  4378.         struct DosList *DosList;
  4379.  
  4380.             /* Lock the list of assignments for reading. */
  4381.  
  4382.         DosList = AttemptLockDosList(LDF_ASSIGNS | LDF_READ);
  4383.  
  4384.             /* Make sure the v37 bug doesn't catch us. */
  4385.  
  4386.         if(((ULONG)DosList) > 1)
  4387.         {
  4388.             STRPTR AssignName;
  4389.  
  4390.                 /* Scan the list... */
  4391.  
  4392.             while(DosList = NextDosEntry(DosList,LDF_ASSIGNS))
  4393.             {
  4394.                     /* Convert the name from icky
  4395.                      * BCPL to `C' style string.
  4396.                      */
  4397.  
  4398.                 AssignName = (STRPTR)BADDR(DosList -> dol_Name);
  4399.  
  4400.                     /* Does the name length match? */
  4401.  
  4402.                 if(AssignName[0] == NameLen)
  4403.                 {
  4404.                         /* Does the name itself match? */
  4405.  
  4406.                     if(!Strnicmp(&AssignName[1],Name,NameLen))
  4407.                     {
  4408.                         Result = TRUE;
  4409.  
  4410.                         break;
  4411.                     }
  4412.                 }
  4413.             }
  4414.  
  4415.                 /* Unlock the list of assignments. */
  4416.  
  4417.             UnLockDosList(LDF_ASSIGNS | LDF_READ);
  4418.         }
  4419.     }
  4420.  
  4421.         /* Return the result. */
  4422.  
  4423.     return(Result);
  4424. }
  4425.  
  4426.     /* LockInAssign(BPTR TheLock,STRPTR TheAssignment):
  4427.      *
  4428.      *    Check if a file lock is part of an assignment.
  4429.      */
  4430.  
  4431. BOOL
  4432. LockInAssign(BPTR TheLock,STRPTR TheAssignment)
  4433. {
  4434.     struct DevProc    *DevProc    = NULL;
  4435.     struct MsgPort    *FileSysTask    = GetFileSysTask();
  4436.     BOOL         Result        = FALSE;
  4437.  
  4438.  
  4439.         /* Loop until all assignments are
  4440.          * processed.
  4441.          */
  4442.  
  4443.     do
  4444.     {
  4445.             /* Get the default filesystem task
  4446.              * in case we stumble upon NULL
  4447.              * directory locks.
  4448.              */
  4449.  
  4450.         if(DevProc = GetDeviceProc(TheAssignment,DevProc))
  4451.         {
  4452.                 /* Set the default filesystem task. */
  4453.  
  4454.             SetFileSysTask(DevProc -> dvp_Port);
  4455.  
  4456.                 /* Is the lock on the list? */
  4457.  
  4458.             if(SameLock(DevProc -> dvp_Lock,TheLock) == LOCK_SAME)
  4459.                 Result = TRUE;
  4460.         }
  4461.         else
  4462.             break;
  4463.     }
  4464.     while(DevProc && (DevProc -> dvp_Flags & DVPF_ASSIGN) && !Result);
  4465.  
  4466.         /* Reset the default filesystem task. */
  4467.  
  4468.     SetFileSysTask(FileSysTask);
  4469.  
  4470.         /* Free device process data. */
  4471.  
  4472.     if(DevProc)
  4473.         FreeDeviceProc(DevProc);
  4474.  
  4475.     return(Result);
  4476. }
  4477.  
  4478.     /* DeleteBitMap(struct BitMap *BitMap):
  4479.      *
  4480.      *    Delete a bitmap created by CreateBitMap().
  4481.      */
  4482.  
  4483. VOID
  4484. DeleteBitMap(struct BitMap *BitMap)
  4485. {
  4486.     if(BitMap)
  4487.     {
  4488.         WaitBlit();
  4489.  
  4490.         if(Kick30)
  4491.             FreeBitMap(BitMap);
  4492.         else
  4493.         {
  4494.             LONG i;
  4495.  
  4496.             for(i = 0 ; i < BitMap -> Depth ; i++)
  4497.             {
  4498.                 if(BitMap -> Planes[i])
  4499.                     FreeVec(BitMap -> Planes[i]);
  4500.             }
  4501.  
  4502.             FreeVecPooled(BitMap);
  4503.         }
  4504.     }
  4505. }
  4506.  
  4507.     /* CreateBitMap(ULONG Width,ULONG Height,ULONG Depth,ULONG Flags,struct BitMap *Friend):
  4508.      *
  4509.      *    Create a new bitmap with given properties.
  4510.      */
  4511.  
  4512. struct BitMap *
  4513. CreateBitMap(ULONG Width,ULONG Height,ULONG Depth,ULONG Flags,struct BitMap *Friend)
  4514. {
  4515.     if(Kick30)
  4516.         return(AllocBitMap(Width,Height,Depth,Flags,Friend));
  4517.     else
  4518.     {
  4519.         struct BitMap    *BitMap;
  4520.         LONG         Plus;
  4521.  
  4522.         if(Depth > 8)
  4523.             Plus = (Depth - 8) * sizeof(PLANEPTR);
  4524.         else
  4525.             Plus = 0;
  4526.  
  4527.         if(BitMap = (struct BitMap *)AllocVecPooled(sizeof(struct BitMap) + Plus,MEMF_CLEAR))
  4528.         {
  4529.             LONG i,PageSize;
  4530.  
  4531.             InitBitMap(BitMap,Depth,Width,Height);
  4532.  
  4533.             PageSize = BitMap -> BytesPerRow * BitMap -> Rows;
  4534.  
  4535.             for(i = 0 ; i < BitMap -> Depth ; i++)
  4536.             {
  4537.                 if(!(BitMap -> Planes[i] = (PLANEPTR)AllocVec(PageSize,MEMF_CHIP)))
  4538.                 {
  4539.                     LONG j;
  4540.  
  4541.                     for(j = 0 ; j < i ; j++)
  4542.                         FreeVec(BitMap -> Planes[j]);
  4543.  
  4544.                     FreeVecPooled(BitMap);
  4545.  
  4546.                     return(NULL);
  4547.                 }
  4548.             }
  4549.  
  4550.             if(Flags & BMF_CLEAR)
  4551.                 BltBitMap(BitMap,0,0,BitMap,0,0,Width,Height,0x00,(1 << Depth) - 1,NULL);
  4552.         }
  4553.  
  4554.         return(BitMap);
  4555.     }
  4556. }
  4557.  
  4558.     /* LaunchCommand(STRPTR Command):
  4559.      *
  4560.      *    Launch a command, try to figure out if it's an ARexx
  4561.      *    command, a plain batch file or a program and act
  4562.      *    accordingly.
  4563.      */
  4564.  
  4565. LONG
  4566. LaunchCommand(STRPTR Command)
  4567. {
  4568.     UBYTE         LocalBuffer[MAX_FILENAME_LENGTH];
  4569.     BPTR         Stream,
  4570.              OutputStream;
  4571.     struct MsgPort    *OldConsoleTask;
  4572.     BOOL         IsScript    = FALSE,
  4573.              IsRexx        = FALSE;
  4574.     LONG         Result;
  4575.     BPTR         CommandFile;
  4576.     UBYTE         NameBuffer[MAX_FILENAME_LENGTH];
  4577.     BPTR         FileLock;
  4578.     STRPTR         OtherName;
  4579.     LONG         i;
  4580.  
  4581.         /* Chop off the arguments. */
  4582.  
  4583.     CopyMem(Command,NameBuffer,MAX_FILENAME_LENGTH - 1);
  4584.  
  4585.     NameBuffer[MAX_FILENAME_LENGTH - 1] = 0;
  4586.  
  4587.     for(i = 0 ; i < MAX_FILENAME_LENGTH ; i++)
  4588.     {
  4589.         if(NameBuffer[i] == ' ')
  4590.         {
  4591.             NameBuffer[i] = 0;
  4592.             break;
  4593.         }
  4594.     }
  4595.  
  4596.         /* Now do something useful. Check if the command
  4597.          * could be an ARexx script.
  4598.          */
  4599.  
  4600.     if(CommandFile = Open(NameBuffer,MODE_OLDFILE))
  4601.     {
  4602.         LONG Len;
  4603.  
  4604.             /* 256 bytes may be not be enough, but then
  4605.              * we're only guessing.
  4606.              */
  4607.  
  4608.         if((Len = Read(CommandFile,LocalBuffer,MAX_FILENAME_LENGTH)) > 0)
  4609.         {
  4610.             register LONG    c;
  4611.             LONG        i;
  4612.  
  4613.             for(i = 0 ; i < Len - 1 ; i++)
  4614.             {
  4615.                 c = LocalBuffer[i];
  4616.  
  4617.                     /* Stop on invalid characters. */
  4618.  
  4619.                 if((c < ' ' && c != '\r' && c != '\n' && c != '\a') || (c >= 127 && c < 160))
  4620.                     break;
  4621.                 else
  4622.                 {
  4623.                         /* Looks like the typical
  4624.                          * introductory comment line.
  4625.                          */
  4626.  
  4627.                     if(c == '/' && LocalBuffer[i + 1] == '*')
  4628.                     {
  4629.                         IsRexx = TRUE;
  4630.                         break;
  4631.                     }
  4632.                 }
  4633.             }
  4634.         }
  4635.  
  4636.         Close(CommandFile);
  4637.     }
  4638.  
  4639.         /* Ok, second check. Does it have the script bit set? */
  4640.  
  4641.     if(FileLock = Lock(NameBuffer,ACCESS_READ))
  4642.     {
  4643.         struct FileInfoBlock __aligned FileInfo;
  4644.  
  4645.         if(Examine(FileLock,&FileInfo))
  4646.         {
  4647.             if(FileInfo . fib_Protection & FIBF_SCRIPT)
  4648.                 IsScript = TRUE;
  4649.         }
  4650.  
  4651.         UnLock(FileLock);
  4652.     }
  4653.  
  4654.         /* If it's an ARexx command, launch it. */
  4655.  
  4656.     if(IsRexx)
  4657.     {
  4658.         SendARexxCommand(Command,TRUE);
  4659.  
  4660.         return(0);
  4661.     }
  4662.  
  4663.         /* If it's a script command, prepend the "Execute "
  4664.          * command. It's not perfect but it should work.
  4665.          */
  4666.  
  4667.     if(IsScript)
  4668.     {
  4669.         if(OtherName = AllocVecPooled(strlen("Execute ") + strlen(Command) + 1,MEMF_ANY))
  4670.         {
  4671.             strcpy(OtherName,"Execute ");
  4672.             strcat(OtherName,Command);
  4673.  
  4674.             Command = OtherName;
  4675.         }
  4676.     }
  4677.     else
  4678.         OtherName = NULL;
  4679.  
  4680.     if(WindowName[0])
  4681.     {
  4682.         UBYTE LocalName[MAXPUBSCREENNAME + 1];
  4683.  
  4684.         if(Window)
  4685.         {
  4686.             if(!GetPubScreenName(Window -> WScreen,LocalName))
  4687.                 LocalName[0] = 0;
  4688.         }
  4689.  
  4690.         if(LocalName[0])
  4691.         {
  4692.             SPrintf(LocalBuffer,WindowName,LocalName);
  4693.  
  4694.             Stream = Open(LocalBuffer,MODE_NEWFILE);
  4695.         }
  4696.         else
  4697.             Stream = Open(WindowName,MODE_NEWFILE);
  4698.     }
  4699.     else
  4700.         Stream = NULL;
  4701.  
  4702.     if(GoodStream(Stream))
  4703.     {
  4704.         OldConsoleTask = GetConsoleTask();
  4705.  
  4706.         SetConsoleTask(((struct FileHandle *)BADDR(Stream)) -> fh_Type);
  4707.  
  4708.         OutputStream = Open("CONSOLE:",MODE_NEWFILE);
  4709.     }
  4710.     else
  4711.         OutputStream = NULL;
  4712.  
  4713.     if(Stream && OutputStream)
  4714.     {
  4715.         Result = SystemTags(Command,
  4716.             SYS_Input,    Stream,
  4717.             SYS_Output,    OutputStream,
  4718.             SYS_UserShell,    TRUE,
  4719.         TAG_DONE);
  4720.     }
  4721.     else
  4722.     {
  4723.         Result = SystemTags(Command,
  4724.             SYS_UserShell,    TRUE,
  4725.         TAG_DONE);
  4726.     }
  4727.  
  4728.     if(OutputStream)
  4729.     {
  4730.         SetConsoleTask(OldConsoleTask);
  4731.         Close(OutputStream);
  4732.     }
  4733.  
  4734.     if(Stream)
  4735.         Close(Stream);
  4736.  
  4737.     if(OtherName)
  4738.         FreeVecPooled(OtherName);
  4739.  
  4740.     return(Result);
  4741. }
  4742.  
  4743.     /* AskDial(struct Window *Parent):
  4744.      *
  4745.      *    This is called when the user is about to start dialing. If the
  4746.      *    dial button/menu item is available with the protective mode
  4747.      *    enabled, a message will be displayed, asking if the line
  4748.      *    should be hung up before proceeding.
  4749.      */
  4750.  
  4751. BOOL
  4752. AskDial(struct Window *Parent)
  4753. {
  4754.     if(!DialItemsAvailable)
  4755.     {
  4756.         if(ShowRequest(Parent,LocaleString(MSG_CANNOT_DIAL_BECAUSE_TXT),LocaleString(MSG_DIAL_CANCEL_TXT)))
  4757.             FullHangup(TRUE);
  4758.         else
  4759.             return(FALSE);
  4760.     }
  4761.  
  4762.     return(TRUE);
  4763. }
  4764.  
  4765.     /* Strcoll(const STRPTR a1,const STRPTR b1):
  4766.      *
  4767.      *    A working strcoll() like routine, which does string comparison
  4768.      *    ignoring case and accents, but taking special national characters
  4769.      *    into account. I am certain about how the german Umlauts should
  4770.      *    be treated, but the treatment for Æ, Þ, Ð and ÿ is pure guesswork...
  4771.      */
  4772.  
  4773. LONG
  4774. Strcoll(STRPTR a1,STRPTR b1)
  4775. {
  4776.     enum {    CHAR_any,
  4777.         CHAR_ae,
  4778.         CHAR_oe,
  4779.         CHAR_ue,
  4780.         CHAR_ss,
  4781.         CHAR_ij
  4782.     };
  4783.  
  4784. #ifdef __SASC
  4785. #pragma msg 62 ignore push
  4786. #endif
  4787.  
  4788.     STATIC UBYTE const noaccent[256] =
  4789.     {
  4790.           0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
  4791.          16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
  4792.         ' ','!', 34,'#','$','%','&', 39,'(',')','*','+',',','-','.','/',
  4793.         '0','1','2','3','4','5','6','7','8','9',':',';','<','=','>','?',
  4794.         '@','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O',
  4795.         'P','Q','R','S','T','U','V','W','X','Y','Z','[','\\',']','^','_',
  4796.         '`','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O',
  4797.         'P','Q','R','S','T','U','V','W','X','Y','Z','{','|','}','~',127,
  4798.         128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
  4799.         144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
  4800.         ' ','¡','¢','£','¤','¥','¦','§','¨','©','ª','«','¬','­','®','¯',
  4801.         '°','±','²','³','´','µ','¶','·','¸','¹','º','»','¼','½','¾','¿',
  4802.         'A','A','A','A','A','A','A','C','E','E','E','E','I','I','I','I',
  4803.         'D','N','O','O','O','O','O','×','O','U','U','U','U','Y','B','S',
  4804.         'A','A','A','A','A','A','A','C','E','E','E','E','I','I','I','I',
  4805.         'D','N','O','O','O','O','O','×','O','U','U','U','U','Y','B','I'
  4806.     };
  4807.  
  4808. #ifdef __SASC
  4809. #pragma msg 62 pop
  4810. #endif
  4811.  
  4812.     STATIC UBYTE const types[256] =
  4813.     {
  4814.         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  4815.         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  4816.         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  4817.         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  4818.         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  4819.         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  4820.         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  4821.         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  4822.         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  4823.         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  4824.         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  4825.         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  4826.         0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,
  4827.         0,0,0,0,0,0,2,0,0,0,0,0,3,0,0,4,
  4828.         0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,
  4829.         0,0,0,0,0,0,2,0,0,0,0,0,3,0,0,5
  4830.     };
  4831.  
  4832.     STRPTR a = (const STRPTR)a1;
  4833.     STRPTR b = (const STRPTR)b1;
  4834.  
  4835.     LONG mul = 1;
  4836.  
  4837. loop:
  4838.  
  4839.     while(*a && *b && noaccent[*a] == noaccent[*b]) { a++; b++; }
  4840.  
  4841.     if(*a || *b)
  4842.     {
  4843.         LONG c = noaccent[*a],d = noaccent[*b];
  4844.  
  4845.         if((types[c] && types[d]) || (!types[c] && !types[d]))
  4846.             return(mul * ((LONG)noaccent[c] - (LONG)noaccent[d]));
  4847.         else
  4848.         {
  4849.             if(types[c] == CHAR_any)
  4850.             {
  4851.                 register STRPTR t;
  4852.                 register LONG e;
  4853.  
  4854.                 e = c;
  4855.                 c = d;
  4856.                 d = e;
  4857.  
  4858.                 t = a;
  4859.                 a = b;
  4860.                 b = t;
  4861.  
  4862.                 mul = -mul;
  4863.             }
  4864.  
  4865.             if(d && noaccent[c] == d)
  4866.             {
  4867.                 switch(types[c])
  4868.                 {
  4869.                     case CHAR_ss:
  4870.  
  4871.                         c = 'S';
  4872.                         break;
  4873.  
  4874.                     case CHAR_ij:
  4875.  
  4876.                         c = 'J';
  4877.                         break;
  4878.  
  4879.                     default:
  4880.  
  4881.                         c = 'E';
  4882.                         break;
  4883.                 }
  4884.  
  4885.                 a++;b++;
  4886.  
  4887.                 d = noaccent[*b];
  4888.  
  4889.                 b++;
  4890.  
  4891.                 if(c == d)
  4892.                     goto loop;
  4893.             }
  4894.  
  4895.             return(mul * ((LONG)noaccent[c] - (LONG)noaccent[d]));
  4896.         }
  4897.     }
  4898.  
  4899.     return(0);
  4900. }
  4901.  
  4902.     /* LaunchProcess(STRPTR Name,VOID (*Entry)(VOID),BPTR Stream):
  4903.      *
  4904.      *    Launch a new process from given entry point, with given
  4905.      *    name and I/O stream.
  4906.      */
  4907.  
  4908. struct Process *
  4909. LaunchProcess(STRPTR Name,VOID (*Entry)(VOID),BPTR Stream)
  4910. {
  4911.     struct MsgPort *ConsoleTask;
  4912.  
  4913.     if(Stream && GoodStream(Stream))
  4914.         ConsoleTask = ((struct FileHandle *)BADDR(Stream)) -> fh_Type;
  4915.     else
  4916.         ConsoleTask = NULL;
  4917.  
  4918.     return(CreateNewProcTags(
  4919.         NP_Entry,    Entry,
  4920.         NP_StackSize,    8000,
  4921.         NP_Name,    Name,
  4922.         NP_Cli,        TRUE,
  4923.         NP_ConsoleTask,    ConsoleTask,
  4924.  
  4925.         ConsoleTask ? TAG_IGNORE : TAG_DONE,0,
  4926.  
  4927.         NP_Output,    ConsoleTask ? NULL : Stream,
  4928.  
  4929.         ConsoleTask ? NP_Input : TAG_IGNORE,Stream,
  4930.     TAG_DONE));
  4931. }
  4932.  
  4933.     /* String2Boolean(STRPTR String):
  4934.      *
  4935.      *    Compare string contents with table contents,
  4936.      *    map the string to a boolean value.
  4937.      */
  4938.  
  4939. BOOL
  4940. String2Boolean(STRPTR String)
  4941. {
  4942.     STATIC STRPTR TrueOptions[] =
  4943.     {
  4944.         "ON",
  4945.         "TRUE",
  4946.         "T",
  4947.         "YES",
  4948.         "Y",
  4949.         "1"
  4950.     };
  4951.  
  4952.     LONG i;
  4953.  
  4954.     for(i = 0 ; i < NumElements(TrueOptions) ; i++)
  4955.     {
  4956.         if(!Stricmp(String,TrueOptions[i]))
  4957.             return(TRUE);
  4958.     }
  4959.  
  4960.     return(FALSE);
  4961. }
  4962.  
  4963.     /* SendMessageGetReply(struct MsgPort *Port,struct Message *Message):
  4964.      *
  4965.      *    Send a message to a given MsgPort and wait for
  4966.      *    the reply.
  4967.      */
  4968.  
  4969. VOID
  4970. SendMessageGetReply(struct MsgPort *Port,struct Message *Message)
  4971. {
  4972.     struct MsgPort LocalPort;
  4973.     struct MsgPort *ReplyPort;
  4974.  
  4975.     ReplyPort = Message->mn_ReplyPort;
  4976.  
  4977.     InitSinglePort(&LocalPort);
  4978.  
  4979.     Message->mn_ReplyPort = &LocalPort;
  4980.  
  4981.     SetSignal(0,SIGF_SINGLE);
  4982.  
  4983.     PutMsg(Port,Message);
  4984.     WaitPort(&LocalPort);
  4985.     GetMsg(&LocalPort);
  4986.  
  4987.     Message->mn_ReplyPort = ReplyPort;
  4988. }
  4989.  
  4990.     /* SetOnlineState(BOOL IsOnline):
  4991.      *
  4992.      *    Set the current online state.
  4993.      */
  4994.  
  4995. VOID
  4996. SetOnlineState(BOOL IsOnline)
  4997. {
  4998.     ObtainSemaphore(&OnlineSemaphore);
  4999.  
  5000.     WasOnline    = Online;
  5001.     Online        = IsOnline;
  5002.  
  5003.     ReleaseSemaphore(&OnlineSemaphore);
  5004. }
  5005.